fog-proxmox 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. checksums.yaml +7 -0
  2. data/.bundle/config +4 -0
  3. data/.codeclimate.yml +14 -0
  4. data/.github/CODE_OF_CONDUCT.md +74 -0
  5. data/.github/CONTRIBUTING.md +20 -0
  6. data/.github/CONTRIBUTORS.md +9 -0
  7. data/.github/FUNDING.yml +12 -0
  8. data/.github/ISSUE_TEMPLATE.md +43 -0
  9. data/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
  10. data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  11. data/.github/SUPPORT.md +9 -0
  12. data/.github/fogproxmox.png +0 -0
  13. data/.github/workflows/ci.yml +79 -0
  14. data/.gitignore +8 -0
  15. data/.rubocop.yml +13 -0
  16. data/.ruby-gemset +1 -0
  17. data/.solargraph.yml +10 -0
  18. data/.vscode/launch.json +96 -0
  19. data/.vscode/settings.json +45 -0
  20. data/.vscode/tasks.json +27 -0
  21. data/Gemfile +23 -0
  22. data/LICENSE +674 -0
  23. data/README.md +79 -0
  24. data/Rakefile +58 -0
  25. data/docs/compute.md +858 -0
  26. data/docs/connection_parameters.md +45 -0
  27. data/docs/getting_started.md +53 -0
  28. data/docs/identity.md +357 -0
  29. data/examples/compute.rb +276 -0
  30. data/examples/identity.rb +190 -0
  31. data/fog-proxmox.gemspec +63 -0
  32. data/lib/fog/compute/proxmox.rb +126 -0
  33. data/lib/fog/compute/proxmox/models/disk.rb +76 -0
  34. data/lib/fog/compute/proxmox/models/disks.rb +51 -0
  35. data/lib/fog/compute/proxmox/models/interface.rb +52 -0
  36. data/lib/fog/compute/proxmox/models/interfaces.rb +44 -0
  37. data/lib/fog/compute/proxmox/models/node.rb +95 -0
  38. data/lib/fog/compute/proxmox/models/nodes.rb +39 -0
  39. data/lib/fog/compute/proxmox/models/server.rb +254 -0
  40. data/lib/fog/compute/proxmox/models/server_config.rb +148 -0
  41. data/lib/fog/compute/proxmox/models/servers.rb +80 -0
  42. data/lib/fog/compute/proxmox/models/snapshot.rb +83 -0
  43. data/lib/fog/compute/proxmox/models/snapshots.rb +47 -0
  44. data/lib/fog/compute/proxmox/models/storage.rb +64 -0
  45. data/lib/fog/compute/proxmox/models/storages.rb +51 -0
  46. data/lib/fog/compute/proxmox/models/task.rb +79 -0
  47. data/lib/fog/compute/proxmox/models/tasks.rb +64 -0
  48. data/lib/fog/compute/proxmox/models/volume.rb +61 -0
  49. data/lib/fog/compute/proxmox/models/volumes.rb +58 -0
  50. data/lib/fog/compute/proxmox/requests/action_server.rb +45 -0
  51. data/lib/fog/compute/proxmox/requests/clone_server.rb +44 -0
  52. data/lib/fog/compute/proxmox/requests/create_backup.rb +42 -0
  53. data/lib/fog/compute/proxmox/requests/create_server.rb +43 -0
  54. data/lib/fog/compute/proxmox/requests/create_snapshot.rb +46 -0
  55. data/lib/fog/compute/proxmox/requests/create_spice.rb +44 -0
  56. data/lib/fog/compute/proxmox/requests/create_term.rb +44 -0
  57. data/lib/fog/compute/proxmox/requests/create_vnc.rb +44 -0
  58. data/lib/fog/compute/proxmox/requests/delete_server.rb +45 -0
  59. data/lib/fog/compute/proxmox/requests/delete_snapshot.rb +47 -0
  60. data/lib/fog/compute/proxmox/requests/delete_volume.rb +40 -0
  61. data/lib/fog/compute/proxmox/requests/get_node_statistics.rb +44 -0
  62. data/lib/fog/compute/proxmox/requests/get_server_config.rb +60 -0
  63. data/lib/fog/compute/proxmox/requests/get_server_status.rb +63 -0
  64. data/lib/fog/compute/proxmox/requests/get_snapshot_config.rb +44 -0
  65. data/lib/fog/compute/proxmox/requests/get_task.rb +41 -0
  66. data/lib/fog/compute/proxmox/requests/get_vnc.rb +44 -0
  67. data/lib/fog/compute/proxmox/requests/get_volume.rb +42 -0
  68. data/lib/fog/compute/proxmox/requests/list_nodes.rb +48 -0
  69. data/lib/fog/compute/proxmox/requests/list_servers.rb +113 -0
  70. data/lib/fog/compute/proxmox/requests/list_snapshots.rb +66 -0
  71. data/lib/fog/compute/proxmox/requests/list_storages.rb +46 -0
  72. data/lib/fog/compute/proxmox/requests/list_tasks.rb +44 -0
  73. data/lib/fog/compute/proxmox/requests/list_volumes.rb +44 -0
  74. data/lib/fog/compute/proxmox/requests/log_task.rb +44 -0
  75. data/lib/fog/compute/proxmox/requests/migrate_server.rb +44 -0
  76. data/lib/fog/compute/proxmox/requests/move_disk.rb +43 -0
  77. data/lib/fog/compute/proxmox/requests/move_volume.rb +43 -0
  78. data/lib/fog/compute/proxmox/requests/next_vmid.rb +42 -0
  79. data/lib/fog/compute/proxmox/requests/resize_container.rb +43 -0
  80. data/lib/fog/compute/proxmox/requests/resize_server.rb +43 -0
  81. data/lib/fog/compute/proxmox/requests/rollback_snapshot.rb +48 -0
  82. data/lib/fog/compute/proxmox/requests/status_task.rb +41 -0
  83. data/lib/fog/compute/proxmox/requests/stop_task.rb +41 -0
  84. data/lib/fog/compute/proxmox/requests/template_server.rb +44 -0
  85. data/lib/fog/compute/proxmox/requests/update_server.rb +44 -0
  86. data/lib/fog/compute/proxmox/requests/update_snapshot.rb +45 -0
  87. data/lib/fog/identity/proxmox.rb +130 -0
  88. data/lib/fog/identity/proxmox/models/domain.rb +65 -0
  89. data/lib/fog/identity/proxmox/models/domain_type.rb +48 -0
  90. data/lib/fog/identity/proxmox/models/domains.rb +45 -0
  91. data/lib/fog/identity/proxmox/models/group.rb +47 -0
  92. data/lib/fog/identity/proxmox/models/groups.rb +44 -0
  93. data/lib/fog/identity/proxmox/models/permission.rb +65 -0
  94. data/lib/fog/identity/proxmox/models/permissions.rb +44 -0
  95. data/lib/fog/identity/proxmox/models/pool.rb +89 -0
  96. data/lib/fog/identity/proxmox/models/pools.rb +46 -0
  97. data/lib/fog/identity/proxmox/models/principal.rb +42 -0
  98. data/lib/fog/identity/proxmox/models/role.rb +48 -0
  99. data/lib/fog/identity/proxmox/models/roles.rb +44 -0
  100. data/lib/fog/identity/proxmox/models/user.rb +60 -0
  101. data/lib/fog/identity/proxmox/models/users.rb +44 -0
  102. data/lib/fog/identity/proxmox/requests/change_password.rb +41 -0
  103. data/lib/fog/identity/proxmox/requests/check_permissions.rb +41 -0
  104. data/lib/fog/identity/proxmox/requests/create_domain.rb +40 -0
  105. data/lib/fog/identity/proxmox/requests/create_group.rb +40 -0
  106. data/lib/fog/identity/proxmox/requests/create_pool.rb +40 -0
  107. data/lib/fog/identity/proxmox/requests/create_role.rb +40 -0
  108. data/lib/fog/identity/proxmox/requests/create_user.rb +40 -0
  109. data/lib/fog/identity/proxmox/requests/delete_domain.rb +40 -0
  110. data/lib/fog/identity/proxmox/requests/delete_group.rb +40 -0
  111. data/lib/fog/identity/proxmox/requests/delete_pool.rb +39 -0
  112. data/lib/fog/identity/proxmox/requests/delete_role.rb +40 -0
  113. data/lib/fog/identity/proxmox/requests/delete_user.rb +39 -0
  114. data/lib/fog/identity/proxmox/requests/get_domain.rb +41 -0
  115. data/lib/fog/identity/proxmox/requests/get_group.rb +41 -0
  116. data/lib/fog/identity/proxmox/requests/get_pool.rb +41 -0
  117. data/lib/fog/identity/proxmox/requests/get_role.rb +41 -0
  118. data/lib/fog/identity/proxmox/requests/get_user.rb +40 -0
  119. data/lib/fog/identity/proxmox/requests/list_domains.rb +41 -0
  120. data/lib/fog/identity/proxmox/requests/list_groups.rb +41 -0
  121. data/lib/fog/identity/proxmox/requests/list_permissions.rb +41 -0
  122. data/lib/fog/identity/proxmox/requests/list_pools.rb +41 -0
  123. data/lib/fog/identity/proxmox/requests/list_roles.rb +40 -0
  124. data/lib/fog/identity/proxmox/requests/list_users.rb +42 -0
  125. data/lib/fog/identity/proxmox/requests/read_version.rb +39 -0
  126. data/lib/fog/identity/proxmox/requests/update_domain.rb +41 -0
  127. data/lib/fog/identity/proxmox/requests/update_group.rb +40 -0
  128. data/lib/fog/identity/proxmox/requests/update_permissions.rb +41 -0
  129. data/lib/fog/identity/proxmox/requests/update_pool.rb +41 -0
  130. data/lib/fog/identity/proxmox/requests/update_role.rb +41 -0
  131. data/lib/fog/identity/proxmox/requests/update_user.rb +41 -0
  132. data/lib/fog/network/proxmox.rb +83 -0
  133. data/lib/fog/network/proxmox/models/network.rb +76 -0
  134. data/lib/fog/network/proxmox/models/networks.rb +48 -0
  135. data/lib/fog/network/proxmox/models/node.rb +74 -0
  136. data/lib/fog/network/proxmox/models/nodes.rb +39 -0
  137. data/lib/fog/network/proxmox/requests/create_network.rb +41 -0
  138. data/lib/fog/network/proxmox/requests/delete_network.rb +42 -0
  139. data/lib/fog/network/proxmox/requests/get_network.rb +43 -0
  140. data/lib/fog/network/proxmox/requests/get_node.rb +41 -0
  141. data/lib/fog/network/proxmox/requests/list_networks.rb +43 -0
  142. data/lib/fog/network/proxmox/requests/list_nodes.rb +42 -0
  143. data/lib/fog/network/proxmox/requests/power_node.rb +43 -0
  144. data/lib/fog/network/proxmox/requests/update_network.rb +42 -0
  145. data/lib/fog/proxmox.rb +115 -0
  146. data/lib/fog/proxmox/attributes.rb +33 -0
  147. data/lib/fog/proxmox/core.rb +135 -0
  148. data/lib/fog/proxmox/errors.rb +64 -0
  149. data/lib/fog/proxmox/hash.rb +39 -0
  150. data/lib/fog/proxmox/helpers/controller_helper.rb +64 -0
  151. data/lib/fog/proxmox/helpers/cpu_helper.rb +42 -0
  152. data/lib/fog/proxmox/helpers/disk_helper.rb +159 -0
  153. data/lib/fog/proxmox/helpers/ip_helper.rb +100 -0
  154. data/lib/fog/proxmox/helpers/nic_helper.rb +115 -0
  155. data/lib/fog/proxmox/json.rb +32 -0
  156. data/lib/fog/proxmox/string.rb +31 -0
  157. data/lib/fog/proxmox/variables.rb +40 -0
  158. data/lib/fog/proxmox/version.rb +24 -0
  159. data/lib/fog/storage/proxmox.rb +29 -0
  160. data/spec/compute_spec.rb +446 -0
  161. data/spec/fixtures/proxmox/compute/containers.yml +12737 -0
  162. data/spec/fixtures/proxmox/compute/identity_ticket.yml +40 -0
  163. data/spec/fixtures/proxmox/compute/nodes.yml +121 -0
  164. data/spec/fixtures/proxmox/compute/servers.yml +24679 -0
  165. data/spec/fixtures/proxmox/compute/snapshots.yml +3321 -0
  166. data/spec/fixtures/proxmox/compute/storages.yml +159 -0
  167. data/spec/fixtures/proxmox/compute/tasks.yml +685 -0
  168. data/spec/fixtures/proxmox/identity/auth.yml +44 -0
  169. data/spec/fixtures/proxmox/identity/domains.yml +701 -0
  170. data/spec/fixtures/proxmox/identity/groups.yml +363 -0
  171. data/spec/fixtures/proxmox/identity/identity_ticket.yml +40 -0
  172. data/spec/fixtures/proxmox/identity/permissions.yml +803 -0
  173. data/spec/fixtures/proxmox/identity/pools.yml +1191 -0
  174. data/spec/fixtures/proxmox/identity/read_version.yml +42 -0
  175. data/spec/fixtures/proxmox/identity/renew.yml +40 -0
  176. data/spec/fixtures/proxmox/identity/roles.yml +363 -0
  177. data/spec/fixtures/proxmox/identity/users.yml +763 -0
  178. data/spec/fixtures/proxmox/network/identity_ticket.yml +40 -0
  179. data/spec/fixtures/proxmox/network/networks.yml +372 -0
  180. data/spec/fixtures/proxmox/pve.home +34 -0
  181. data/spec/hash_spec.rb +42 -0
  182. data/spec/helpers/controller_helper_spec.rb +145 -0
  183. data/spec/helpers/cpu_helper_spec.rb +70 -0
  184. data/spec/helpers/disk_helper_spec.rb +210 -0
  185. data/spec/helpers/ip_helper_spec.rb +160 -0
  186. data/spec/helpers/nic_helper_spec.rb +136 -0
  187. data/spec/identity_spec.rb +322 -0
  188. data/spec/network_spec.rb +67 -0
  189. data/spec/proxmox_vcr.rb +95 -0
  190. data/spec/spec_helper.rb +40 -0
  191. metadata +547 -0
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Tristan Robert
4
+
5
+ # This file is part of Fog::Proxmox.
6
+
7
+ # Fog::Proxmox is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+
12
+ # Fog::Proxmox is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ module Fog
21
+ module Proxmox
22
+ # module String mixins
23
+ module String
24
+ def self.to_boolean(text)
25
+ return true if text == true || text =~ (/(true|t|yes|y|1)$/i)
26
+ return false if text == false || text.empty? || text =~ (/(false|f|no|n|0)$/i)
27
+ raise ArgumentError.new("invalid value for Boolean: \"#{text}\"")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Tristan Robert
4
+
5
+ # This file is part of Fog::Proxmox.
6
+
7
+ # Fog::Proxmox is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+
12
+ # Fog::Proxmox is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ module Fog
21
+ module Proxmox
22
+ # module Variables mixins
23
+ module Variables
24
+ def self.to_variables(instance, hash, prefix)
25
+ hash.select { |key| key.to_s.start_with? prefix }.each do |key, value|
26
+ instance.instance_variable_set "@#{key}".to_sym, value
27
+ end
28
+ end
29
+
30
+ def self.to_hash(instance, prefix)
31
+ hash = {}
32
+ instance.instance_variables.select { |variable| variable.to_s.start_with? '@' + prefix }.each do |param|
33
+ name = param.to_s[1..-1]
34
+ hash.store(name.to_sym, instance.instance_variable_get(param))
35
+ end
36
+ hash
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Tristan Robert
4
+
5
+ # This file is part of Fog::Proxmox.
6
+
7
+ # Fog::Proxmox is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+
12
+ # Fog::Proxmox is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ module Fog
21
+ module Proxmox
22
+ VERSION = '0.13.0'
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2018 Tristan Robert
3
+
4
+ # This file is part of Fog::Proxmox.
5
+
6
+ # Fog::Proxmox is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Fog::Proxmox is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ # frozen_string_literal: true
20
+
21
+ module Fog
22
+ module Proxmox
23
+ # Procmox storage service
24
+ class Storage < Fog::Service
25
+ # Models
26
+ model_path 'fog/storage/proxmox'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,446 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Tristan Robert
4
+
5
+ # This file is part of Fog::Proxmox.
6
+
7
+ # Fog::Proxmox is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+
12
+ # Fog::Proxmox is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Fog::Proxmox. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ require 'spec_helper'
21
+ require_relative './proxmox_vcr'
22
+
23
+ describe Fog::Proxmox::Compute do
24
+ before :all do
25
+ @proxmox_vcr = ProxmoxVCR.new(
26
+ vcr_directory: 'spec/fixtures/proxmox/compute',
27
+ service_class: Fog::Proxmox::Compute
28
+ )
29
+ @service = @proxmox_vcr.service
30
+ @pve_url = @proxmox_vcr.url
31
+ @username = @proxmox_vcr.username
32
+ @password = @proxmox_vcr.password
33
+ @ticket = @proxmox_vcr.ticket
34
+ @csrftoken = @proxmox_vcr.csrftoken
35
+ end
36
+
37
+ it 'Manage tasks' do
38
+ VCR.use_cassette('tasks') do
39
+ # List all tasks
40
+ filters = { limit: 1 }
41
+ node_name = 'pve'
42
+ node = @service.nodes.get node_name
43
+ tasks = node.tasks.all(filters)
44
+ _(tasks).wont_be_nil
45
+ _(tasks).wont_be_empty
46
+ _(tasks.size).must_equal 1
47
+ # Get task
48
+ upid = tasks[0].upid
49
+ task = node.tasks.get(upid)
50
+ _(task).wont_be_nil
51
+ # Stop task
52
+ task.stop
53
+ task.wait_for { finished? }
54
+ _(task.finished?).must_equal true
55
+ end
56
+ end
57
+
58
+ it 'Manage nodes' do
59
+ VCR.use_cassette('nodes') do
60
+ # Get node
61
+ node_name = 'pve'
62
+ node = @service.nodes.get node_name
63
+ # Get statistics data
64
+ data = node.statistics
65
+ _(data).wont_be_nil
66
+ _(data).wont_be_empty
67
+ # Get statistics image
68
+ data = node.statistics('rrd', { timeframe: 'hour', ds: 'cpu,memused', cf: 'AVERAGE' })
69
+ _(data).wont_be_nil
70
+ _(data['image']).wont_be_nil
71
+ end
72
+ end
73
+
74
+ it 'Manage storages' do
75
+ VCR.use_cassette('storages') do
76
+ # Get node
77
+ node_name = 'pve'
78
+ node = @service.nodes.get node_name
79
+ # List all storages
80
+ storages = node.storages.all
81
+ _(storages).wont_be_nil
82
+ _(storages).wont_be_empty
83
+ _(storages.size).must_equal 2
84
+ # List by content type
85
+ storages = node.storages.list_by_content_type 'iso'
86
+ _(storages).wont_be_nil
87
+ _(storages).wont_be_empty
88
+ _(storages.size).must_equal 1
89
+ # Get storage
90
+ storage = node.storages.get('local')
91
+ _(storage).wont_be_nil
92
+ _(storage.identity).must_equal 'local'
93
+ end
94
+ end
95
+
96
+ it 'CRUD servers' do
97
+ VCR.use_cassette('servers') do
98
+ node_name = 'pve'
99
+ node = @service.nodes.get node_name
100
+ # Get next vmid
101
+ vmid = node.servers.next_id
102
+ server_hash = { vmid: vmid }
103
+ # Check valid vmid
104
+ valid = node.servers.id_valid? vmid
105
+ _(valid).must_equal true
106
+ # Check not valid vmid
107
+ valid = node.servers.id_valid? 99
108
+ _(valid).must_equal false
109
+ # Create 1st time
110
+ server = node.servers.create(server_hash)
111
+ ok = server.persisted?
112
+ _(ok).must_equal true
113
+ # Check already used vmid
114
+ valid = node.servers.id_valid? vmid
115
+ _(valid).must_equal false
116
+ # Clone server
117
+ newid = node.servers.next_id
118
+ # Get server
119
+ server = node.servers.get vmid
120
+ _(server).wont_be_nil
121
+ # Backup it
122
+ server.backup(compress: 'lzo')
123
+ # Get this backup image
124
+ # Find available backup volumes
125
+ volume = server.backups.first
126
+ _(volume).wont_be_nil
127
+ # Restore it
128
+ server.restore(volume, storage: 'local')
129
+ # Delete it
130
+ volume.destroy
131
+ # Add hdd
132
+ # Find available storages with images
133
+ storages = node.storages.list_by_content_type 'images'
134
+ storage = storages[0]
135
+ virtio0 = { id: 'virtio0', storage: storage.storage, size: '1' }
136
+ ide0 = { id: 'ide0', storage: storage.storage, size: '1' }
137
+ options = { backup: 0, replicate: 0 }
138
+ server.attach(virtio0, options)
139
+ server.attach(ide0, options)
140
+ server.detach('ide0')
141
+ server.detach('unused0')
142
+ sleep 1
143
+ # Clone it (linked fails)
144
+ server.clone(newid, full: 1)
145
+ # Get clone
146
+ clone = node.servers.get newid
147
+ # Template this clone (read-only)
148
+ clone.create_template
149
+ # Get clone disk image
150
+ image = clone.images.first
151
+ _(image).wont_be_nil
152
+ # Delete clone
153
+ clone.destroy
154
+ _(proc do
155
+ clone = node.servers.get newid
156
+ end).must_raise Fog::Errors::NotFound
157
+ # Create 2nd time must fails
158
+ _(proc do
159
+ node.servers.create server_hash
160
+ end).must_raise Excon::Errors::InternalServerError
161
+ # Update config server
162
+ # Add empty cdrom
163
+ config_hash = { ide2: 'none,media=cdrom' }
164
+ server.update(config_hash)
165
+ # Resize disk server
166
+ server.extend('virtio0', '+1G')
167
+ # Move disk server
168
+ server.move('virtio0', 'local')
169
+ # Add network interface
170
+ config_hash = { net0: 'virtio,bridge=vmbr0' }
171
+ server.update(config_hash)
172
+ # Add start at boot, keyboard fr,
173
+ # linux 4.x os type, kvm hardware disabled (proxmox guest in virtualbox) and vga enabled to console
174
+ config_hash = { onboot: 1, keyboard: 'fr', ostype: 'l26', kvm: 0 }
175
+ server.update(config_hash)
176
+ # server config
177
+ config = server.config
178
+ _(config.identity).must_equal vmid
179
+ disks = server.config.disks
180
+ interfaces = server.config.interfaces
181
+ _(interfaces).wont_be_nil
182
+ _(interfaces).wont_be_empty
183
+ net0 = interfaces.get('net0')
184
+ _(net0).wont_be_nil
185
+ _(disks).wont_be_nil
186
+ _(disks).wont_be_empty
187
+ virtio0 = disks.get('virtio0')
188
+ _(virtio0).wont_be_nil
189
+ ide2 = disks.get('ide2')
190
+ _(ide2).wont_be_nil
191
+ # Get a mac adress
192
+ mac_address = server.config.mac_addresses.first
193
+ _(mac_address).wont_be_nil
194
+ # all servers
195
+ servers_all = node.servers.all
196
+ _(servers_all).wont_be_empty
197
+ _(servers_all).must_include server
198
+ # server not running exception
199
+ _(proc do
200
+ server.start_console(websocket: 1)
201
+ end).must_raise Fog::Proxmox::Errors::ServiceError
202
+ # Start server
203
+ server.action('start')
204
+ server.wait_for { ready? }
205
+ status = server.ready?
206
+ _(status).must_equal true
207
+ # server vga not set exception
208
+ _(proc do
209
+ server.start_console(websocket: 1)
210
+ end).must_raise Fog::Proxmox::Errors::ServiceError
211
+ # Stop server
212
+ server.action('stop')
213
+ server.wait_for { server.status == 'stopped' }
214
+ status = server.status
215
+ _(status).must_equal 'stopped'
216
+ server.update(vga: 'std')
217
+ # Start server
218
+ server.action('start')
219
+ server.wait_for { ready? }
220
+ status = server.ready?
221
+ _(status).must_equal true
222
+ vnc = server.start_console(websocket: 1)
223
+ _(vnc['cert']).wont_be_nil
224
+ port = server.connect_vnc(vnc)
225
+ _(port).wont_be_nil
226
+ # Stop server
227
+ server.action('stop')
228
+ server.wait_for { server.status == 'stopped' }
229
+ status = server.status
230
+ _(status).must_equal 'stopped'
231
+ server.update(serial0: 'socket', vga: 'serial0')
232
+ # Start server
233
+ server.action('start')
234
+ server.wait_for { ready? }
235
+ status = server.ready?
236
+ _(status).must_equal true
237
+ term = server.start_console
238
+ _(term['ticket']).wont_be_nil
239
+ # Stop server
240
+ server.action('stop')
241
+ server.wait_for { server.status == 'stopped' }
242
+ status = server.status
243
+ _(status).must_equal 'stopped'
244
+ server.update(vga: 'qxl')
245
+ # Start server
246
+ server.action('start')
247
+ server.wait_for { ready? }
248
+ status = server.ready?
249
+ _(status).must_equal true
250
+ spice = server.start_console
251
+ _(spice['password']).wont_be_nil
252
+ # Suspend server
253
+ server.action('suspend')
254
+ server.wait_for { server.qmpstatus == 'paused' }
255
+ qmpstatus = server.qmpstatus
256
+ _(qmpstatus).must_equal 'paused'
257
+ # Resume server
258
+ server.action('resume')
259
+ server.wait_for { ready? }
260
+ status = server.ready?
261
+ _(status).must_equal true
262
+ # Stop server
263
+ server.action('stop')
264
+ server.wait_for { server.status == 'stopped' }
265
+ status = server.status
266
+ _(status).must_equal 'stopped'
267
+ _(proc do
268
+ server.action('hello')
269
+ end).must_raise Fog::Errors::Error
270
+ # Delete
271
+ server.destroy
272
+ _(proc do
273
+ node.servers.get vmid
274
+ end).must_raise Fog::Errors::NotFound
275
+ end
276
+ end
277
+
278
+ it 'CRUD snapshots' do
279
+ VCR.use_cassette('snapshots') do
280
+ node_name = 'pve'
281
+ node = @service.nodes.get node_name
282
+ vmid = node.servers.next_id
283
+ server_hash = { vmid: vmid }
284
+ node.servers.create server_hash
285
+ # Create
286
+ snapname = 'snapshot1'
287
+ server = node.servers.get vmid
288
+ snapshot_hash = { name: snapname }
289
+ server.snapshots.create(snapshot_hash)
290
+ # Find by id
291
+ snapshot = server.snapshots.get snapname
292
+ _(snapshot).wont_be_nil
293
+ # Update
294
+ snapshot.description = 'Snapshot 1'
295
+ snapshot.update
296
+ # all snapshots
297
+ snapshots_all = server.snapshots.all
298
+ _(snapshots_all).wont_be_nil
299
+ _(snapshots_all).wont_be_empty
300
+ _(snapshots_all).must_include snapshot
301
+ # Delete
302
+ snapshot.destroy
303
+ server.destroy
304
+ end
305
+ end
306
+
307
+ it 'CRUD containers' do
308
+ VCR.use_cassette('containers') do
309
+ node_name = 'pve'
310
+ node = @service.nodes.get node_name
311
+ _(node).wont_be_nil
312
+ # Get next vmid
313
+ vmid = node.containers.next_id
314
+ ostemplate = 'local:vztmpl/alpine-3.10-default_20190626_amd64.tar.xz'
315
+ container_hash = { ostemplate: ostemplate, storage: 'local-lvm', password: 'proxmox01', rootfs: 'local-lvm:1' }
316
+ # Check valid vmid
317
+ valid = node.containers.id_valid? vmid
318
+ _(valid).must_equal true
319
+ # Check not valid vmid
320
+ valid = node.containers.id_valid? 99
321
+ _(valid).must_equal false
322
+ # Create 1st time
323
+ node.containers.create(container_hash.merge(vmid: vmid))
324
+ # Check already used vmid
325
+ valid = node.containers.id_valid? vmid
326
+ _(valid).must_equal false
327
+ # Clone container
328
+ newid = node.containers.next_id
329
+ # Get container
330
+ container = node.containers.get vmid
331
+ _(container).wont_be_nil
332
+ rootfs_a = container.config.disks.select { |disk| disk.rootfs? }
333
+ _(rootfs_a).wont_be_empty
334
+ rootfs = rootfs_a.first
335
+ _(rootfs).wont_be_nil
336
+ # Backup it
337
+ container.backup(compress: 'lzo')
338
+ # Get this backup image
339
+ # Find available backup volumes
340
+ backup = container.backups.first
341
+ _(container).wont_be_nil
342
+ # Restore it
343
+ container.restore(backup, storage: 'local-lvm')
344
+ # Delete it
345
+ backup.destroy
346
+ _(container.backups).must_be_empty
347
+ # Add mount points
348
+ # Find available storages with images
349
+ storages = node.storages.list_by_content_type 'images'
350
+ storage = storages[0]
351
+ mp0 = { id: 'mp0', storage: storage.storage, size: '1' }
352
+ options = { mp: '/opt/app', backup: 0, replicate: 0, quota: 1 }
353
+ container.attach(mp0, options)
354
+ # Fetch mount points
355
+ mount_points = container.config.disks.select { |disk| disk.mount_point? }
356
+ _(mount_points).wont_be_empty
357
+ _(mount_points.get('mp0')).wont_be_nil
358
+ # Remove mount points
359
+ container.detach('mp0')
360
+ container.detach('unused0')
361
+ sleep 1
362
+ # Clone it
363
+ container.clone(newid)
364
+ # Get clone
365
+ clone = node.containers.get newid
366
+ # Template this clone (read-only)
367
+ clone.template
368
+ # Get clone disk image
369
+ image = clone.images.first
370
+ _(image).wont_be_nil
371
+ # Delete clone
372
+ clone.destroy
373
+ _(proc do
374
+ node.containers.get newid
375
+ end).must_raise Fog::Errors::NotFound
376
+ # Create 2nd time must fails
377
+ _(proc do
378
+ node.containers.create(container_hash.merge(vmid: vmid))
379
+ end).must_raise Excon::Errors::InternalServerError
380
+ # Update config container
381
+ # Resize rootfs container
382
+ container.extend('rootfs', '+5M')
383
+ # Move rootfs container and delete original
384
+ container.move('rootfs', 'local-lvm', delete: 1)
385
+ # Add network interface
386
+ config_hash = { net0: 'bridge=vmbr0,name=eth0,ip=dhcp,ip6=dhcp' }
387
+ container.update(config_hash)
388
+ # Add start at boot, keyboard fr,
389
+ # linux os type alpine
390
+ config_hash = { onboot: 1, ostype: 'alpine' }
391
+ container.update(config_hash)
392
+ # get container config
393
+ config = container.config
394
+ _(config).wont_be_nil
395
+ _(config.identity).must_equal vmid
396
+ # Fetch nics
397
+ interfaces = container.config.interfaces
398
+ _(interfaces).wont_be_empty
399
+ _(interfaces.get('net0')).wont_be_nil
400
+ # Get a mac address
401
+ mac_address = container.config.mac_addresses.first
402
+ _(mac_address).wont_be_nil
403
+ # all containers
404
+ containers_all = node.containers.all
405
+ _(containers_all).wont_be_nil
406
+ _(containers_all).wont_be_empty
407
+ _(containers_all.first.vmid).must_equal container.vmid.to_s
408
+ # Start container
409
+ container.action('start')
410
+ container.wait_for { ready? }
411
+ status = container.ready?
412
+ _(status).must_equal true
413
+ # Start console
414
+ _(proc do
415
+ container.start_console
416
+ end).must_raise Fog::Errors::Error
417
+ spice = container.start_console(console: 'spice')
418
+ _(spice['password']).wont_be_nil
419
+ # Suspend container (: command 'lxc-checkpoint -n 100 -s -D /var/lib/vz/dump' failed: exit code 1)
420
+ # container.action('suspend')
421
+ # container.wait_for { container.qmpstatus == 'paused' }
422
+ # qmpstatus = container.qmpstatus
423
+ # _(qmpstatus).must_equal 'paused'
424
+ # Resume server
425
+ # container.action('resume')
426
+ # container.wait_for { ready? }
427
+ # status = container.ready?
428
+ # _(status).must_equal true
429
+ # Stop container
430
+ container.action('stop')
431
+ container.wait_for { container.status == 'stopped' }
432
+ status = container.status
433
+ _(status).must_equal 'stopped'
434
+ _(proc do
435
+ container.action('hello')
436
+ end).must_raise Fog::Errors::Error
437
+ # Delete
438
+ container.destroy
439
+ # Delete container does not delete images
440
+ storage.volumes.each(&:destroy)
441
+ _(proc do
442
+ node.containers.get vmid
443
+ end).must_raise Fog::Errors::NotFound
444
+ end
445
+ end
446
+ end