pve 0.1.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/LICENSE.txt +661 -0
- data/README.adoc +12 -0
- data/Rakefile +2 -0
- data/lib/pve/cli/base.rb +44 -20
- data/lib/pve/cli/ct.rb +34 -14
- data/lib/pve/cli/ha.rb +3 -3
- data/lib/pve/cli/qm.rb +25 -9
- data/lib/pve/cli/storage.rb +97 -0
- data/lib/pve/cli/task.rb +1 -1
- data/lib/pve/cli.rb +101 -25
- data/lib/pve/helper.rb +63 -24
- data/lib/pve/proxmox.rb +135 -33
- data/lib/pve/templates.rb +57 -15
- data/lib/pve/version.rb +1 -1
- data/pve.gemspec +1 -1
- metadata +7 -6
- data/Gemfile.lock +0 -70
- data/lib/pve/qm.rb +0 -32
data/lib/pve/helper.rb
CHANGED
@@ -1,15 +1,36 @@
|
|
1
|
+
module IPAddress::ToSWithNetmaskForNetworks
|
2
|
+
refine IPAddress::IPv6 do
|
3
|
+
def to_s
|
4
|
+
128 == prefix ? super() : to_string
|
5
|
+
end
|
6
|
+
end
|
7
|
+
refine IPAddress::IPv4 do
|
8
|
+
def to_s
|
9
|
+
32 == prefix ? super() : to_string
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
1
15
|
class Measured
|
16
|
+
class V
|
17
|
+
attr_reader :value, :length
|
18
|
+
|
19
|
+
def initialize( value, length = nil) @value, @length = value, length || value.length end
|
20
|
+
def inspect() "#<Measured::V #{@value.inspect} (#{@length})>" end
|
21
|
+
alias :to_s :value
|
22
|
+
alias :to_str :value
|
23
|
+
end
|
24
|
+
|
2
25
|
class <<self
|
3
26
|
def bytes1 v
|
4
27
|
v = v.to_f
|
5
|
-
return
|
28
|
+
return units '%d ' % v , :B if 512 > v
|
6
29
|
%w[KiB MiBy GiByt TiByte ExiByte PetiByte].each_with_index do |m|
|
7
30
|
v /= 1024
|
8
|
-
|
9
|
-
#return "%d %s" % [v, m] if 512 > v
|
10
|
-
return "%.1f %s" % [v, m] if 512 > v
|
31
|
+
return units '%.1f ' % v, m if 512 > v
|
11
32
|
end
|
12
|
-
|
33
|
+
units '%d ' % v, :PetiByte
|
13
34
|
end
|
14
35
|
|
15
36
|
def bytes2 v
|
@@ -26,21 +47,28 @@ class Measured
|
|
26
47
|
end
|
27
48
|
alias bytes bytes2
|
28
49
|
|
50
|
+
def units val, unit
|
51
|
+
v = "#{val}\e[1;30m#{unit}\e[0m"
|
52
|
+
V.new v, v.length - 11
|
53
|
+
end
|
54
|
+
|
29
55
|
def seconds i
|
30
56
|
i = i.to_i
|
31
|
-
return
|
32
|
-
return
|
57
|
+
return V.new "\e[1;30m·\e[0m", 1 if 0 == i
|
58
|
+
return units '%d ' % i, :s if 90 > i
|
33
59
|
i /= 60
|
34
|
-
return
|
60
|
+
return units '%d ' % i, :mi if 90 > i
|
35
61
|
i /= 60
|
36
|
-
return
|
62
|
+
return units '%d ' % i, :hou if 36 > i
|
37
63
|
i /= 24
|
38
|
-
return
|
64
|
+
return units '%d ' % i, :days if 14 > i
|
39
65
|
j = i / 7
|
40
|
-
return
|
41
|
-
i
|
42
|
-
return
|
43
|
-
|
66
|
+
return units '%d ' % j, :weeks if 8 > j
|
67
|
+
j = i / 30
|
68
|
+
return units '%d ' % j, :months if 11 > j
|
69
|
+
i /= 365.0
|
70
|
+
return units '%.2f ' % i, :years if 550 > i
|
71
|
+
units '%d ' % i, :years
|
44
72
|
end
|
45
73
|
end
|
46
74
|
end
|
@@ -58,10 +86,8 @@ class ColoredString
|
|
58
86
|
|
59
87
|
def length() @string.length end
|
60
88
|
alias size length
|
61
|
-
#def to_str() self end
|
62
89
|
def to_s() "\e[#{@color_codes}m#{@string}\e[0m" end
|
63
90
|
alias to_str to_s
|
64
|
-
#alias inspect to_str
|
65
91
|
|
66
92
|
include Comparable
|
67
93
|
def <=>(o) @string <=> o.string end
|
@@ -70,9 +96,10 @@ end
|
|
70
96
|
|
71
97
|
|
72
98
|
class TablizedOutput
|
73
|
-
def initialize header, stdout: nil
|
99
|
+
def initialize header, stdout: nil, format: nil
|
74
100
|
@header = header.map &:to_s
|
75
101
|
@columnc = header.size
|
102
|
+
@format = format || ['>']*@columnc
|
76
103
|
@maxs = header.map &:length
|
77
104
|
@stdout ||= STDOUT
|
78
105
|
@lines = []
|
@@ -86,7 +113,7 @@ class TablizedOutput
|
|
86
113
|
class V < B
|
87
114
|
attr_reader :v, :s
|
88
115
|
def initialize( v, s=nil) @v, @s = v, s || "#{v}" end
|
89
|
-
def to_s() @s end
|
116
|
+
def to_s() @s.to_s end
|
90
117
|
def length() @s.length end
|
91
118
|
def inspect() "#<TO:V #{@v.inspect} #{@s.inspect}>" end
|
92
119
|
end
|
@@ -98,10 +125,10 @@ class TablizedOutput
|
|
98
125
|
def inspect() "#<TO:Percentage #{@v}%>" end
|
99
126
|
|
100
127
|
def to_s
|
101
|
-
y =
|
128
|
+
y = (v*w).round
|
102
129
|
x = (100*v).round
|
103
130
|
r = "%*s" % [w, 0==x ? '·' : x]
|
104
|
-
"\e[
|
131
|
+
"\e[1;4;#{0.75>v ? 32 : 31}m#{r[0...y]}\e[0m#{r[y..-1]}"
|
105
132
|
end
|
106
133
|
end
|
107
134
|
|
@@ -122,7 +149,6 @@ class TablizedOutput
|
|
122
149
|
end
|
123
150
|
|
124
151
|
def print order: nil
|
125
|
-
format = "#{(["\e[%%sm%% %ds\e[0m"] * @columnc).join( ' ') % @maxs}\n"
|
126
152
|
ls = @lines
|
127
153
|
if order
|
128
154
|
eval <<-EOC, binding, __FILE__, 1+__LINE__
|
@@ -132,9 +158,22 @@ class TablizedOutput
|
|
132
158
|
}
|
133
159
|
EOC
|
134
160
|
end
|
135
|
-
|
136
|
-
|
137
|
-
|
161
|
+
@stdout.puts \
|
162
|
+
@header.each_with_index.map {|s, i|
|
163
|
+
"#{' ' * (@maxs[i] - s.length)}#{s}"
|
164
|
+
}.join( ' ')
|
165
|
+
ls.each_with_index do |l|
|
166
|
+
@stdout.puts \
|
167
|
+
l.each_with_index.map {|s, i|
|
168
|
+
pad = ' ' * (@maxs[i] - s.length)
|
169
|
+
case @format[i]
|
170
|
+
when '<'
|
171
|
+
"#{s}#{pad}"
|
172
|
+
else
|
173
|
+
"#{pad}#{s}"
|
174
|
+
end
|
175
|
+
}.join( ' ')
|
176
|
+
end
|
138
177
|
end
|
139
178
|
|
140
179
|
def virt v
|
data/lib/pve/proxmox.rb
CHANGED
@@ -123,10 +123,14 @@ module Proxmox
|
|
123
123
|
n.send :__update__, data
|
124
124
|
end
|
125
125
|
private :__new__
|
126
|
+
|
127
|
+
def fetch predata
|
128
|
+
__new__( predata).refresh!
|
129
|
+
end
|
126
130
|
end
|
127
131
|
|
128
|
-
def respond_to? method
|
129
|
-
|
132
|
+
def respond_to? method, also_private = false
|
133
|
+
instance_variable_defined?( "@#{method}") or super(method, also_private)
|
130
134
|
end
|
131
135
|
|
132
136
|
def method_missing method, *args, &exe
|
@@ -147,6 +151,7 @@ module Proxmox
|
|
147
151
|
initialize
|
148
152
|
self
|
149
153
|
end
|
154
|
+
private :__update__
|
150
155
|
|
151
156
|
def refresh!
|
152
157
|
__update__ rest_get( @rest_prefix)
|
@@ -176,9 +181,13 @@ module Proxmox
|
|
176
181
|
def === t
|
177
182
|
@name =~ t or @vmid.to_s =~ t or @sid =~ t
|
178
183
|
end
|
184
|
+
|
185
|
+
def rest_prefix
|
186
|
+
@rest_prefix ||= "/nodes/#{@node}"
|
187
|
+
end
|
179
188
|
|
180
189
|
def initialize
|
181
|
-
|
190
|
+
rest_prefix
|
182
191
|
@sid = "nd:#{@node}"
|
183
192
|
@name = @node
|
184
193
|
end
|
@@ -191,6 +200,20 @@ module Proxmox
|
|
191
200
|
rest_get( "#{@rest_prefix}/lxc").map {|d| LXC.send :__new__, d.merge( node: self, t: 'ct') }
|
192
201
|
end
|
193
202
|
|
203
|
+
def aplinfo
|
204
|
+
return [] if offline?
|
205
|
+
rest_get( "#{@rest_prefix}/aplinfo").map do |d|
|
206
|
+
AplInfo.send :__new__, d.merge( node: self, t: 'apl')
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def storage
|
211
|
+
return [] if offline?
|
212
|
+
rest_get( "#{@rest_prefix}/storage").map do |d|
|
213
|
+
Storage.send :__new__, d.merge( node: self, t: 'sm')
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
194
217
|
def qemu
|
195
218
|
return [] if offline?
|
196
219
|
rest_get( "#{@rest_prefix}/qemu").map {|d| Qemu.send :__new__, d.merge( node: self, t: 'qm') }
|
@@ -211,21 +234,51 @@ module Proxmox
|
|
211
234
|
end
|
212
235
|
|
213
236
|
class Task < Base
|
214
|
-
|
237
|
+
class Status < Base
|
238
|
+
def rest_prefix
|
239
|
+
@rest_prefix ||= '/nodes/%s/tasks/%s/status' % [@node.node, @upid]
|
240
|
+
end
|
241
|
+
|
242
|
+
def refresh!
|
243
|
+
d = rest_get @rest_prefix
|
244
|
+
d[:starttime] &&= Time.at d[:starttime]
|
245
|
+
d = {exitstatus: nil}.merge d
|
246
|
+
__update__ d.merge( node: @node, t: 'status', upid: @upid, task: @task)
|
247
|
+
end
|
248
|
+
|
249
|
+
def initialize
|
250
|
+
rest_prefix
|
251
|
+
@sid = upid
|
252
|
+
end
|
253
|
+
|
254
|
+
def inspect
|
255
|
+
h = instance_variables - %i[@node @task @sid @rest_prefix @upid @t]
|
256
|
+
h.map! {|k| "#{k[1..-1]}=#{instance_variable_get(k).inspect}" }
|
257
|
+
"#<#{self.class.name}|#{@upid} node=#{@node.node} #{h.join ' '}>"
|
258
|
+
end
|
259
|
+
|
260
|
+
def running?() 'running' == @status end
|
261
|
+
def finished?() 'stopped' == @status end
|
262
|
+
alias stopped? finished?
|
263
|
+
def successfull?() stopped? ? 'OK' == @exitstatus : nil end
|
264
|
+
def failed?() stopped? ? 'OK' != @exitstatus : nil end
|
265
|
+
end
|
266
|
+
|
267
|
+
def rest_prefix
|
215
268
|
@rest_prefix = "/nodes/#{@node.node}/tasks/#{upid}"
|
269
|
+
end
|
270
|
+
|
271
|
+
def initialize
|
272
|
+
rest_prefix
|
216
273
|
@sid = upid
|
217
274
|
end
|
218
275
|
|
219
276
|
def inspect
|
220
|
-
"#<#{self.class.name} #{upid}>"
|
277
|
+
"#<#{self.class.name} #{@upid}>"
|
221
278
|
end
|
222
279
|
|
223
|
-
#def finished?
|
224
|
-
# rest_get( "/nodes/#{node}/tasks/")
|
225
|
-
#end
|
226
|
-
|
227
280
|
def status
|
228
|
-
|
281
|
+
Status.fetch node: @node, task: self, upid: @upid
|
229
282
|
end
|
230
283
|
|
231
284
|
def log start: nil, limit: nil
|
@@ -235,8 +288,7 @@ module Proxmox
|
|
235
288
|
|
236
289
|
class Hosted < Base
|
237
290
|
def refresh!
|
238
|
-
|
239
|
-
__update__ rest_get( "#{@rest_prefix}/status/current").merge( node: node, t: t)
|
291
|
+
__update__ rest_get( "#{@rest_prefix}/status/current").merge( node: @node, t: @t)
|
240
292
|
end
|
241
293
|
|
242
294
|
def === t
|
@@ -331,6 +383,11 @@ module Proxmox
|
|
331
383
|
r.delete :delete if r[:delete].empty?
|
332
384
|
rest_put "#{@rest_prefix}/config", r
|
333
385
|
end
|
386
|
+
|
387
|
+
def resize disk, size
|
388
|
+
upid = rest_put "#{@rest_prefix}/resize", disk: disk, size: size
|
389
|
+
Task.send :__new__, node: @node, host: self, upid: upid
|
390
|
+
end
|
334
391
|
end
|
335
392
|
|
336
393
|
class Qemu < Hosted
|
@@ -341,19 +398,15 @@ module Proxmox
|
|
341
398
|
|
342
399
|
def find_by_vmid vmid
|
343
400
|
vmid = vmid.to_s
|
344
|
-
|
345
|
-
|
346
|
-
return l if l.vmid == vmid
|
347
|
-
end
|
401
|
+
all.each do |l|
|
402
|
+
return l if l.vmid == vmid
|
348
403
|
end
|
349
404
|
nil
|
350
405
|
end
|
351
406
|
|
352
407
|
def find_by_name name
|
353
|
-
|
354
|
-
|
355
|
-
return l if l.name == name
|
356
|
-
end
|
408
|
+
all.each do |l|
|
409
|
+
return l if l.name == name
|
357
410
|
end
|
358
411
|
nil
|
359
412
|
end
|
@@ -387,8 +440,12 @@ module Proxmox
|
|
387
440
|
end
|
388
441
|
end
|
389
442
|
|
443
|
+
def rest_prefix
|
444
|
+
@rest_prefix ||= "/nodes/%s/qemu/%d" % [@node.node, @vmid]
|
445
|
+
end
|
446
|
+
|
390
447
|
def initialize
|
391
|
-
|
448
|
+
rest_prefix
|
392
449
|
@sid = "qm:#{@vmid}"
|
393
450
|
end
|
394
451
|
|
@@ -399,6 +456,11 @@ module Proxmox
|
|
399
456
|
def exec *args
|
400
457
|
node.exec 'qm', 'guest', 'exec', vmid, '--', *args
|
401
458
|
end
|
459
|
+
|
460
|
+
def resize disk, size
|
461
|
+
upid = rest_put "#{@rest_prefix}/resize", disk: disk, size: size
|
462
|
+
Task.send :__new__, node: @node, host: self, upid: upid
|
463
|
+
end
|
402
464
|
end
|
403
465
|
|
404
466
|
class LXC < Hosted
|
@@ -490,14 +552,19 @@ module Proxmox
|
|
490
552
|
swap: tmplt.swap,
|
491
553
|
unprivileged: tmplt.unprivileged,
|
492
554
|
}.delete_if {|k,v| v.nil? }
|
493
|
-
|
555
|
+
|
556
|
+
temp = LXC.send :__new__, node: node, vmid: options[:vmid], name: name, hostname: options[:hostname]
|
494
557
|
upid = rest_post( "/nodes/%s/lxc" % node.node, **options)
|
495
|
-
Task.send :__new__, node: node, host:
|
558
|
+
Task.send :__new__, node: node, host: temp, upid: upid
|
496
559
|
end
|
497
560
|
end
|
498
561
|
|
562
|
+
def rest_prefix
|
563
|
+
@rest_prefix ||= "/nodes/%s/lxc/%d" % [@node.node, @vmid]
|
564
|
+
end
|
565
|
+
|
499
566
|
def initialize
|
500
|
-
|
567
|
+
rest_prefix
|
501
568
|
@sid = "ct:#{@vmid}"
|
502
569
|
end
|
503
570
|
|
@@ -515,8 +582,12 @@ module Proxmox
|
|
515
582
|
end
|
516
583
|
|
517
584
|
class HA < Base
|
585
|
+
def rest_prefix
|
586
|
+
@rest_prefix ||= "/cluster/ha/resources/#{virt.sid}"
|
587
|
+
end
|
588
|
+
|
518
589
|
def initialize
|
519
|
-
|
590
|
+
rest_prefix
|
520
591
|
end
|
521
592
|
|
522
593
|
class <<self
|
@@ -576,20 +647,51 @@ module Proxmox
|
|
576
647
|
self
|
577
648
|
end
|
578
649
|
|
579
|
-
def started?
|
580
|
-
|
650
|
+
def started?() 'started' == self.state end
|
651
|
+
def stopped?() 'stopped' == self.state end
|
652
|
+
def error?() 'error' == self.state end
|
653
|
+
def active?() ! ! digest end
|
654
|
+
end
|
655
|
+
|
656
|
+
class Storage < Base
|
657
|
+
def rest_prefix
|
658
|
+
@rest_prefix ||= "/nodes/#{@node.node}/storage/#{@storage}"
|
581
659
|
end
|
582
660
|
|
583
|
-
def
|
584
|
-
|
661
|
+
def content
|
662
|
+
rest_get( "#{@rest_prefix}/content").map do |c|
|
663
|
+
Content.send :__new__, c.merge( node: @node, storage: self, t: 'smc')
|
664
|
+
end
|
585
665
|
end
|
586
666
|
|
587
|
-
def
|
588
|
-
|
667
|
+
def initialize() rest_prefix end
|
668
|
+
|
669
|
+
def to_s() "#{@node.node}:#{@storage}" end
|
670
|
+
|
671
|
+
class Content < Base
|
672
|
+
def rest_prefix
|
673
|
+
@rest_prefix ||= "/nodes/#{@node.node}/storage/#{@storage}/content/#{@content}"
|
674
|
+
end
|
675
|
+
|
676
|
+
def initialize() rest_prefix end
|
677
|
+
def to_s() "#{node.node} #{volid}" end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
class AplInfo < Base
|
682
|
+
def rest_prefix
|
683
|
+
@rest_prefix ||= "/nodes/#{@node.node}/aplinfo"
|
589
684
|
end
|
590
685
|
|
591
|
-
def
|
592
|
-
|
686
|
+
def initialize() rest_prefix end
|
687
|
+
def name() @template end
|
688
|
+
def system?() 'system' == @section end
|
689
|
+
def debian?() %r[\Adebian-] =~ @os end
|
690
|
+
def lxc?() 'lxc' == @type end
|
691
|
+
|
692
|
+
def download storage
|
693
|
+
upid = rest_post "#{@rest_prefix}", template: @template, storage: storage.to_s
|
694
|
+
Task.send :__new__, node: @node, host: self, upid: upid
|
593
695
|
end
|
594
696
|
end
|
595
697
|
end
|
data/lib/pve/templates.rb
CHANGED
@@ -27,14 +27,27 @@ module PVE::CTTemplate
|
|
27
27
|
File.read( options[:'ssh-public-keys-file'] || '/root/.ssh/authorized_keys')
|
28
28
|
end
|
29
29
|
|
30
|
+
def _ipv4 ip, gw
|
31
|
+
return [ip, nil] if %w[dhcp].include? ip
|
32
|
+
ip = IPAddress::IPv4.new ip
|
33
|
+
[ip.to_string, gw || ip.hosts.last.to_s]
|
34
|
+
end
|
35
|
+
|
36
|
+
def _ipv6 ip, gw
|
37
|
+
return [ip, nil] if %w[dhcp auto].include? ip
|
38
|
+
ip = IPAddress::IPv6.new ip
|
39
|
+
[ip.to_string, gw || ip.hosts.last.to_s]
|
40
|
+
end
|
41
|
+
|
30
42
|
def net0()
|
31
43
|
if options.ipv4 || options.ipv6
|
32
|
-
ipv4 =
|
44
|
+
ipv4, gw4 = _ipv4( options.ipv4, options.gateway4)
|
45
|
+
ipv6, gw6 = _ipv6( options.ipv6, options.gateway6)
|
33
46
|
{
|
34
47
|
name: 'eth0',
|
35
48
|
bridge: 'vmbr1',
|
36
|
-
ip: ipv4
|
37
|
-
gw:
|
49
|
+
ip: ipv4, ip6: ipv6,
|
50
|
+
gw: gw4, gw6: gw6,
|
38
51
|
}
|
39
52
|
end
|
40
53
|
end
|
@@ -44,6 +57,10 @@ module PVE::CTTemplate
|
|
44
57
|
end
|
45
58
|
|
46
59
|
class Default < Base
|
60
|
+
def self.help
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
47
64
|
def self.requirements
|
48
65
|
{
|
49
66
|
node: [:string, false, "Create CT on this node."],
|
@@ -62,7 +79,7 @@ module PVE::CTTemplate
|
|
62
79
|
:'ssh-public-keys-file' => [:string, false, "Read SSH-Public-Keys from file."],
|
63
80
|
ipv4: [:string, false, "IPv4-Address with net-size."],
|
64
81
|
gateway4: [:string, false, "IPv4-Address of gateway."],
|
65
|
-
ipv6: [:string, false, "IPv6-Address with net-size."],
|
82
|
+
ipv6: [:string, false, "IPv6-Address with net-size or auto."],
|
66
83
|
gateway6: [:string, false, "IPv6-Address of gateway."],
|
67
84
|
storage: [:string, false, "Device will be create on this Storage (default: local"],
|
68
85
|
}
|
@@ -70,12 +87,24 @@ module PVE::CTTemplate
|
|
70
87
|
end
|
71
88
|
|
72
89
|
class Datacenter < Base
|
90
|
+
def self.help
|
91
|
+
<<-EOF.gsub /^ {6}/, ''
|
92
|
+
Datacenter provides an interface for special network-settings.
|
93
|
+
Networks in Datacenters are often based on this behaviour:
|
94
|
+
A Network has an ID like 99.
|
95
|
+
This defines the VLANs: 2099 for Layer2/3099 for Layer3.
|
96
|
+
The IPv4-Range would be 10.99.0.0/16, but container will be put static in 10.99.255.0/24.
|
97
|
+
IPv6 uses RADV, so we do not need to know the IPv6-Range => auto.
|
98
|
+
VMID can be generated by Network-ID, too: smallest unused VMID in 100*ID.
|
99
|
+
EOF
|
100
|
+
end
|
101
|
+
|
73
102
|
def self.requirements
|
74
103
|
{
|
75
104
|
node: [:string, false, "Create CT on this node."],
|
76
105
|
name: [:string, true, "Set (uniq) name"],
|
77
106
|
arch: [:enum, false, "Architecture", %w[amd64 i386 arm64 armhf]],
|
78
|
-
vmid: [:numeric,
|
107
|
+
vmid: [:numeric, false, "VM-ID. Proxmox internal number (100...)"],
|
79
108
|
ostype: [:string, true, "OS-Type (OS or distribution)"],
|
80
109
|
cmode: [:enum, false, "Console-mode", %w[shell console tty]],
|
81
110
|
cores: [:numeric, false, "Count of cores"],
|
@@ -87,11 +116,12 @@ module PVE::CTTemplate
|
|
87
116
|
:'ssh-public-keys' => [:string, false, "SSH-Public-Keys, which should be added to root-user in CT."],
|
88
117
|
:'ssh-public-keys-file' => [:string, false, "Read SSH-Public-Keys from file."],
|
89
118
|
:'network-id' => [:numeric, true, "Put Container to this VLAN and use a random IPv4-Address for this CT."],
|
90
|
-
ipv4: [:string, false, "IPv4-Address with net-size."],
|
119
|
+
ipv4: [:string, false, "IPv4-Address with net-size or dhcp."],
|
91
120
|
gateway4: [:string, false, "IPv4-Address of gateway."],
|
92
|
-
ipv6: [:string, false, "IPv6-Address with net-size."],
|
121
|
+
ipv6: [:string, false, "IPv6-Address with net-size or auto|dhcp."],
|
93
122
|
gateway6: [:string, false, "IPv6-Address of gateway."],
|
94
123
|
storage: [:string, false, "Device will be create on this Storage (default: root)"],
|
124
|
+
ostemplate: [:string, false, "OS-Template eg. local:vztmpl/superlinux-1.2-amd64.tar.xz"],
|
95
125
|
}
|
96
126
|
end
|
97
127
|
|
@@ -111,15 +141,27 @@ module PVE::CTTemplate
|
|
111
141
|
end
|
112
142
|
|
113
143
|
def net0
|
144
|
+
ipv4, gw4 =
|
145
|
+
if options.ipv4
|
146
|
+
_ipv4( options.ipv4, options.gateway4)
|
147
|
+
else
|
148
|
+
self.ipv4_gw
|
149
|
+
end
|
150
|
+
ipv6, gw6 =
|
151
|
+
if options.ipv6
|
152
|
+
_ipv6( options.ipv6, options.gateway6)
|
153
|
+
else
|
154
|
+
['auto', nil]
|
155
|
+
end
|
114
156
|
{
|
115
157
|
name: 'eth0',
|
116
158
|
bridge: 'vmbr1',
|
117
159
|
tag: 2000+network_id,
|
118
160
|
mtu: 9166,
|
119
161
|
firewall: 1,
|
120
|
-
ip: ipv4
|
121
|
-
|
122
|
-
}
|
162
|
+
ip: ipv4, gw: gw4,
|
163
|
+
ip6: ipv6, gw6: gw6,
|
164
|
+
}.delete_if {|k,v| v.nil? }
|
123
165
|
end
|
124
166
|
|
125
167
|
def vmid
|
@@ -130,14 +172,13 @@ module PVE::CTTemplate
|
|
130
172
|
IPAddress::IPv4.new "10.#{network_id}.255.0/24"
|
131
173
|
end
|
132
174
|
|
133
|
-
def
|
134
|
-
return
|
135
|
-
return @ipv4 if @ipv4
|
175
|
+
def ipv4_gw
|
176
|
+
return @ipv4_gw if @ipv4_gw
|
136
177
|
ipv4s = network.hosts
|
137
178
|
@virts.each do |v|
|
138
179
|
v.config[:network].each {|n| ipv4s.delete n[:ip] if n[:ip] }
|
139
180
|
end
|
140
|
-
@
|
181
|
+
@ipv4_gw = [ipv4s.first.to_string, network.last.to_s]
|
141
182
|
end
|
142
183
|
|
143
184
|
def ostemplate
|
@@ -145,7 +186,8 @@ module PVE::CTTemplate
|
|
145
186
|
options.ostemplate ||
|
146
187
|
case ostype
|
147
188
|
when 'debian'
|
148
|
-
|
189
|
+
# TODO: how to determine which template?
|
190
|
+
'local:vztmpl/debian-11-standard_11.0-1_amd64.tar.gz'
|
149
191
|
else
|
150
192
|
raise ArgumentError, "OS-Template for ostype #{ostype} not found or ostemplate not provided."
|
151
193
|
end
|
data/lib/pve/version.rb
CHANGED
data/pve.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.metadata["source_code_uri"] = spec.homepage
|
20
20
|
spec.metadata["changelog_uri"] = spec.homepage
|
21
21
|
|
22
|
-
spec.add_dependency 'dencli', '~> 0.3
|
22
|
+
spec.add_dependency 'dencli', '~> 0.5.3'
|
23
23
|
spec.add_dependency 'rest-client', '~> 2.1'
|
24
24
|
spec.add_dependency 'ipaddress', '~> 0.8.3'
|
25
25
|
spec.add_dependency 'activesupport', '>= 2'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pve
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Knauf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dencli
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.3
|
19
|
+
version: 0.5.3
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.3
|
26
|
+
version: 0.5.3
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rest-client
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,8 +104,9 @@ extra_rdoc_files: []
|
|
104
104
|
files:
|
105
105
|
- ".gitignore"
|
106
106
|
- Gemfile
|
107
|
-
-
|
107
|
+
- LICENSE.txt
|
108
108
|
- README.adoc
|
109
|
+
- Rakefile
|
109
110
|
- bin/pvecli
|
110
111
|
- lib/pve.rb
|
111
112
|
- lib/pve/cli.rb
|
@@ -114,10 +115,10 @@ files:
|
|
114
115
|
- lib/pve/cli/ha.rb
|
115
116
|
- lib/pve/cli/node.rb
|
116
117
|
- lib/pve/cli/qm.rb
|
118
|
+
- lib/pve/cli/storage.rb
|
117
119
|
- lib/pve/cli/task.rb
|
118
120
|
- lib/pve/helper.rb
|
119
121
|
- lib/pve/proxmox.rb
|
120
|
-
- lib/pve/qm.rb
|
121
122
|
- lib/pve/templates.rb
|
122
123
|
- lib/pve/version.rb
|
123
124
|
- pve.gemspec
|