pve 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2f41d6fba5690429b625a55d147bf468834c1e705d6e73fdcd879566037dd47
4
- data.tar.gz: 5237da733be939f52f26818f6c12a20d2389c5a26e8ba7343cbce62bcb280001
3
+ metadata.gz: a06ddcb47642c05e1741f36743dddc8549fe0a662d72246b8965d63474f437a2
4
+ data.tar.gz: 458054ab599bc236cbae0e708180778a38b4d9136d6278f4c3866047af0f4819
5
5
  SHA512:
6
- metadata.gz: adfe44900fc74f93932b12ffed27abced7d33e04c910fad519b406755d8d9f9de140347341da45a3a35d4e315f4c5e7b5286af2ec4fbdf6ec2f9116a94221224
7
- data.tar.gz: 3b55ec2a97b1973ae66d08e17cb50c70ec765305292748fe306bb99e3dd30bf33a46c5bc824570a8786e832c767f422e4da814ad14dd0497ab83ec707d46e0e9
6
+ metadata.gz: e967e72848d1ca823b8ebb85737a78018116e3ac28c7bc070d1d3a8936ad6c79e9e09a2ff11344f0ce1aa62fa54634602e3993f5081126bf8f72d2b7ac841a32
7
+ data.tar.gz: 673189e3d7318103b2dad96f653c072c1cef4a1a9a329aa920b17e8f43ecc8741763379b2a2a3f07ccaaf8af8c46eac2c9cef715225f6b6faa8353edaafa1a8a
data/lib/pve/cli.rb CHANGED
@@ -59,16 +59,18 @@ class PVE::Cli
59
59
  secs ||= 0.1
60
60
  spinners, spin, logn = "▖▘▝▗", 0, 0
61
61
  STDERR.puts task.upid
62
+ host = task.host&.name
62
63
  loop do
63
64
  s = task.status
64
65
  if s[:exitstatus]
65
- STDERR.printf "\r[%s] %s %s\e[J\n",
66
- task.host ? task.host.name : s[:id],
66
+ STDERR.printf "\r[%s] %s %s %s\e[J\n",
67
+ host || s[:id],
67
68
  case s[:exitstatus]
68
69
  when "OK" then "\e[32;1m✓\e[0m"
69
70
  else "\e[31;1m✗\e[0m"
70
71
  end,
71
- s[:status]
72
+ text && "#{text}:",
73
+ s[:status] == 'stopped' ? :finished : s[:status]
72
74
  return task
73
75
  end
74
76
  log = task.log start: logn
@@ -78,7 +80,10 @@ class PVE::Cli
78
80
  log.each {|l| puts l[:t] }
79
81
  logn = log.last[:n]
80
82
  end
81
- STDERR.printf "\r[%s] \e[33;1m%s\e[0m %s...\e[J", task.host ? task.host.name : s[:id], spinners[spin = (spin + 1) % 4], text || "Working"
83
+ STDERR.printf "\r[%s] \e[33;1m%s\e[0m %s...\e[J",
84
+ host || s[:id],
85
+ spinners[spin = (spin + 1) % 4],
86
+ text || "Working"
82
87
  sleep secs
83
88
  end
84
89
  end
@@ -112,12 +117,12 @@ class PVE::Cli
112
117
  end
113
118
 
114
119
  def create klass, template, timeout: nil, fire: nil, secs: nil, start: nil, **options
115
- options[:start] = true if fire and start
120
+ options[:start] = fire && start
116
121
  task = klass.create template, **options
117
122
  return if fire
118
123
  wait task, text: "Creating"
119
124
  host = task.host.refresh!
120
- start host, timeout: timeout, secs: secs
125
+ start host, timeout: timeout, secs: secs if start
121
126
  end
122
127
 
123
128
  def destroy ct, timeout: nil, fire: nil, secs: nil
@@ -151,7 +156,7 @@ class PVE::Cli
151
156
  def call *argv
152
157
  cli.call *argv
153
158
  rescue RestClient::ExceptionWithResponse
154
- STDERR.puts "#$! - #{$!.response} (#{$!.class})", $!.backtrace.map {|b|" #{b}"}
159
+ STDERR.puts "#$! - #{$!.response} (#{$!.class})" #, $!.backtrace.map {|b|" #{b}"}
155
160
  rescue UsageError, DenCli::UsageError
156
161
  STDERR.puts $!
157
162
  exit 1
data/lib/pve/cli/base.rb CHANGED
@@ -2,6 +2,8 @@ require 'pmap'
2
2
 
3
3
  class PVE::Cli
4
4
 
5
+ using IPAddress::ToSWithNetmaskForNetworks
6
+
5
7
  def cli_base
6
8
  cli.cmd :list, "List CT/VM-IDs", aliases: ['ls'], &lambda {|target=nil|
7
9
  connect
data/lib/pve/cli/ct.rb CHANGED
@@ -57,13 +57,19 @@ def cli_ct
57
57
  if %w[-h --help].include? template
58
58
  STDERR.puts "Usage: ct create TEMPLATE -h # Shows template-related options"
59
59
  STDERR.puts " ct create TEMPLATE [OPTIONS] # Creates a container"
60
+ STDERR.puts " ct create -l # Listing available templates"
60
61
  exit 1
62
+ elsif %w[-l --list].include? template
63
+ STDERR.puts PVE::CTTemplate.constants.reject {|c|:Base==c}.map {|c|c.to_s.titlecase.dasherize.downcase}
64
+ exit 0
61
65
  end
62
66
  ctopts = {}
63
67
  OptionParser.new do |opts|
68
+ ctt = PVE::CTTemplate.const_get template.classify
64
69
  opts.banner = <<EOU
65
70
  Usage: ct create #{template} [options]
66
71
 
72
+ #{ctt.help}
67
73
  Options: (*=Required)
68
74
  EOU
69
75
  opts.on '-h', '--help', " Help!" do
@@ -75,7 +81,6 @@ EOU
75
81
  opts.on( '-f', '--[no-]-fire', " Do not wait till running") {|v| ctopts[:start] = v }
76
82
  opts.on( '-t', '--timeout=TIMEOUT', " Wait for max TIMEOUT seconds (default: endless)") {|v| ctopts[:timeout] = v }
77
83
  opts.on( '-s', '--seconds=SECONDS', " Check every SECONDS for state (default: 0.2)") {|v| ctopts[:seconds] = v }
78
- ctt = PVE::CTTemplate.const_get template.classify
79
84
  ctt.requirements.each do |name, (type, req, desc, *args)|
80
85
  req = req ? "*" : " "
81
86
  case type
@@ -94,12 +99,19 @@ EOU
94
99
  create Proxmox::LXC, template, **ctopts
95
100
  })
96
101
 
97
- ct_cli.cmd( :config, '', &lambda {|name_or_id|
102
+ ct_cli.cmd( :config, 'Shows current config', &lambda {|name_or_id|
98
103
  connect
99
104
  ct = Proxmox::LXC.find! name_or_id
100
105
  STDOUT.puts ct.config.to_json
101
106
  })
102
107
 
108
+ ct_cli.cmd( :resize, 'Resize a disk', &lambda {|name_or_id, disk, size|
109
+ connect
110
+ ct = Proxmox::LXC.find! name_or_id
111
+ task = ct.resize disk, size
112
+ wait task, text: "Resizing #{ct.sid} #{disk} to #{size}"
113
+ })
114
+
103
115
  ct_cli.cmd( :destroy, '', min: 7, &lambda {|name_or_id, fire:, secs:, timeout:, i_really_want_to_destroy:|
104
116
  raise UsageError, "Name/ID is not what you want to destroy" unless name_or_id == i_really_want_to_destroy
105
117
  connect
data/lib/pve/helper.rb CHANGED
@@ -1,3 +1,17 @@
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
2
16
  class <<self
3
17
  def bytes1 v
data/lib/pve/proxmox.rb CHANGED
@@ -331,6 +331,11 @@ module Proxmox
331
331
  r.delete :delete if r[:delete].empty?
332
332
  rest_put "#{@rest_prefix}/config", r
333
333
  end
334
+
335
+ def resize disk, size
336
+ upid = rest_put "#{@rest_prefix}/resize", disk: disk, size: size
337
+ Task.send :__new__, node: @node, host: self, upid: upid
338
+ end
334
339
  end
335
340
 
336
341
  class Qemu < Hosted
@@ -490,9 +495,10 @@ module Proxmox
490
495
  swap: tmplt.swap,
491
496
  unprivileged: tmplt.unprivileged,
492
497
  }.delete_if {|k,v| v.nil? }
493
- @temp = LXC.send :__new__, node: node, vmid: options[:vmid], name: name, hostname: options[:hostname]
498
+
499
+ temp = LXC.send :__new__, node: node, vmid: options[:vmid], name: name, hostname: options[:hostname]
494
500
  upid = rest_post( "/nodes/%s/lxc" % node.node, **options)
495
- Task.send :__new__, node: node, host: @temp, upid: upid
501
+ Task.send :__new__, node: node, host: temp, upid: upid
496
502
  end
497
503
  end
498
504
 
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 = IPAddress::IPv4.new options.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.to_string,
37
- gw: options.gateway || ipv4.hosts.last.to_s
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, true, "VM-ID. Proxmox internal number (100...)"],
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.to_string,
121
- gw: ipv4.hosts.last.to_s,
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 ipv4
134
- return options.ipv4 if options.ipv4
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
- @ipv4 = ipv4s.first
181
+ @ipv4_gw = [ipv4s.first.to_string, network.last.to_s]
141
182
  end
142
183
 
143
184
  def ostemplate
data/lib/pve/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module PVE
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
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.1.2
4
+ version: 0.1.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-04-21 00:00:00.000000000 Z
11
+ date: 2021-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dencli
@@ -117,7 +117,6 @@ files:
117
117
  - lib/pve/cli/task.rb
118
118
  - lib/pve/helper.rb
119
119
  - lib/pve/proxmox.rb
120
- - lib/pve/qm.rb
121
120
  - lib/pve/templates.rb
122
121
  - lib/pve/version.rb
123
122
  - pve.gemspec
data/lib/pve/qm.rb DELETED
@@ -1,32 +0,0 @@
1
- class PVE::Cli
2
- def cli_qm
3
- cli.sub :qm, "Virtual Machines", aliases: %w[v vm qemu], &lambda {|qm|
4
- qm.cmd :list, "List VM-IDs", aliases: ['ls'], &lambda {|node=nil|
5
- connect
6
- nodes = Proxmox::Node.all
7
- nodes = nodes.select {|n| node == n.name } if node
8
- nodes.flat_map do |n|
9
- n.qemu.map {|c| c.vmid.to_i }
10
- end.sort.each {|c| puts c }
11
- }
12
-
13
- qm.cmd :status, "List VMs with status", aliases: [nil], &lambda {|node=nil|
14
- connect
15
- to = TablizedOutput.new %w[Status HA ID Name Host Uptime CPU Mem/MiB Disk/MiB]
16
- nodes = Proxmox::Node.all
17
- nodes = nodes.select {|n| node == n.name } if node
18
- nodes.each do |n|
19
- n.qemu.each &to.method( :virt)
20
- end
21
- to.print order: [3]
22
- }
23
-
24
- qm.cmd :exec, "Executes Command in VM via qemu-guest-agent", min: 4, &lambda {|name_or_id, *command|
25
- connect
26
- STDERR.puts "! #{$?.exitstatus}" unless Proxmox::Qemu.find!( name_or_id).exec *command
27
- }
28
-
29
- qm.cmd 'help', '', aliases: ['-h', '--help'], &lambda {|*args| help qm, *args }
30
- }
31
- end
32
- end