Class: VagrantPlugins::Proxmox::Connection

Inherits:
Object
  • Object
show all
Includes:
RequiredParameters
Defined in:
lib/vagrant-proxmox/proxmox/connection.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RequiredParameters

#required

Constructor Details

#initialize(api_url, opts = {}) ⇒ Connection

Returns a new instance of Connection.



34
35
36
37
38
39
40
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 34

def initialize api_url, opts = {}
	@api_url = api_url
	@vm_id_range = opts[:vm_id_range] || (900..999)
	@task_timeout = opts[:task_timeout] || 60
	@task_status_check_interval = opts[:task_status_check_interval] || 2
	@imgcopy_timeout = opts[:imgcopy_timeout] || 120
end

Instance Attribute Details

#api_urlObject (readonly)

Returns the value of attribute api_url.



26
27
28
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 26

def api_url
  @api_url
end

#csrf_tokenObject (readonly)

Returns the value of attribute csrf_token.



28
29
30
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 28

def csrf_token
  @csrf_token
end

#imgcopy_timeoutObject

Returns the value of attribute imgcopy_timeout.



32
33
34
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 32

def imgcopy_timeout
  @imgcopy_timeout
end

#task_status_check_intervalObject

Returns the value of attribute task_status_check_interval.



31
32
33
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 31

def task_status_check_interval
  @task_status_check_interval
end

#task_timeoutObject

Returns the value of attribute task_timeout.



30
31
32
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 30

def task_timeout
  @task_timeout
end

#ticketObject (readonly)

Returns the value of attribute ticket.



27
28
29
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 27

def ticket
  @ticket
end

#vm_id_rangeObject

Returns the value of attribute vm_id_range.



29
30
31
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 29

def vm_id_range
  @vm_id_range
end

Instance Method Details

#clone_vm(node: required('node'), vm_type: required('node'), params: required('params')) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 103

def clone_vm node: required('node'), vm_type: required('node'), params: required('params')
	vm_id = params[:vmid]
	params.delete(:vmid)
	params.delete(:ostype)
	params.delete(:ide2)
	params.delete(:sata0)
	params.delete(:sockets)
	params.delete(:cores)
	params.delete(:description)
	params.delete(:memory)
	params.delete(:net0)
	response = post "/nodes/#{node}/#{vm_type}/#{vm_id}/clone", params
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.create_vm_timeout'
end

#config_clone(node: required('node'), vm_type: required('node'), params: required('params')) ⇒ Object



118
119
120
121
122
123
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 118

def config_clone node: required('node'), vm_type: required('node'), params: required('params')
	vm_id = params[:vmid]
	params.delete(:vmid)
	response = post "/nodes/#{node}/#{vm_type}/#{vm_id}/config", params
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.create_vm_timeout'
end

#create_vm(node: required('node'), vm_type: required('node'), params: required('params')) ⇒ Object



98
99
100
101
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 98

def create_vm node: required('node'), vm_type: required('node'), params: required('params')
	response = post "/nodes/#{node}/#{vm_type}", params
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.create_vm_timeout'
end

#delete_file(filename: required('filename'), content_type: required('content_type'), node: required('node'), storage: required('storage')) ⇒ Object



174
175
176
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 174

def delete_file filename: required('filename'), content_type: required('content_type'), node: required('node'), storage: required('storage')
	delete "/nodes/#{node}/storage/#{storage}/content/#{content_type}/#{File.basename filename}"
end

#delete_vm(vm_id) ⇒ Object



92
93
94
95
96
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 92

def delete_vm vm_id
	vm_info = get_vm_info vm_id
	response = delete "/nodes/#{vm_info[:node]}/#{vm_info[:type]}/#{vm_id}"
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.destroy_vm_timeout'
end

#get_free_vm_idObject



149
150
151
152
153
154
155
156
157
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 149

def get_free_vm_id
                             # to avoid collisions in multi-vm setups
	sleep (rand(1..3) + 0.1 * rand(0..9))
	response = get "/cluster/resources?type=vm"
	allowed_vm_ids = vm_id_range.to_set
	used_vm_ids = response[:data].map { |vm| vm[:vmid] }
	free_vm_ids = (allowed_vm_ids - used_vm_ids).sort
	free_vm_ids.empty? ? raise(VagrantPlugins::Proxmox::Errors::NoVmIdAvailable) : free_vm_ids.first
end

#get_node_ip(node, interface) ⇒ Object



183
184
185
186
187
188
189
190
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 183

def get_node_ip node, interface
	begin
		response = get "/nodes/#{node}/network/#{interface}"
		response[:data][:address]
	rescue ApiError::ServerError
		:not_created
	end
end

#get_node_listObject



54
55
56
57
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 54

def get_node_list
	nodelist = get '/nodes'
	nodelist[:data].map { |n| n[:node] }
end

#get_qemu_template_id(template) ⇒ Object



159
160
161
162
163
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 159

def get_qemu_template_id template
	response = get "/cluster/resources?type=vm"
	found_ids = response[:data].select { |vm| vm[:type] == 'qemu' }.select { |vm| vm[:template] == 1 }.select { |vm| vm[:name] == template }.map { |vm| vm[:vmid] }
	found_ids.empty? ? raise(VagrantPlugins::Proxmox::Errors::NoTemplateAvailable) : found_ids.first
end

#get_vm_config(node: required('node'), vm_id: required('node'), vm_type: required('node')) ⇒ Object



125
126
127
128
129
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 125

def get_vm_config node: required('node'), vm_id: required('node'), vm_type: required('node')
	response = get "/nodes/#{node}/#{vm_type}/#{vm_id}/config"
	response = response[:data]
	response.empty? ? raise(VagrantPlugins::Proxmox::Errors::VMConfigError) : response
end

#get_vm_state(vm_id) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 59

def get_vm_state vm_id
	vm_info = get_vm_info vm_id
	if vm_info
		begin
			response = get "/nodes/#{vm_info[:node]}/#{vm_info[:type]}/#{vm_id}/status/current"
			states = {'running' => :running,
								'stopped' => :stopped}
			states[response[:data][:status]]
		rescue ApiError::ServerError
			:not_created
		end
	else
		:not_created
	end
end

#list_storage_files(node: required('node'), storage: required('storage')) ⇒ Object



178
179
180
181
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 178

def list_storage_files node: required('node'), storage: required('storage')
	res = get "/nodes/#{node}/storage/#{storage}/content"
	res[:data].map { |e| e[:volid] }
end

#login(username: required('username'), password: required('password')) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 42

def  username: required('username'), password: required('password')
	begin
		response = post "/access/ticket", username: username, password: password
		@ticket = response[:data][:ticket]
		@csrf_token = response[:data][:CSRFPreventionToken]
	rescue ApiError::ServerError
		raise ApiError::InvalidCredentials
	rescue => x
		raise ApiError::ConnectionError, x.message
	end
end

#shutdown_vm(vm_id) ⇒ Object



143
144
145
146
147
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 143

def shutdown_vm vm_id
	vm_info = get_vm_info vm_id
	response = post "/nodes/#{vm_info[:node]}/#{vm_info[:type]}/#{vm_id}/status/shutdown", nil
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.shutdown_vm_timeout'
end

#start_vm(vm_id) ⇒ Object



131
132
133
134
135
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 131

def start_vm vm_id
	vm_info = get_vm_info vm_id
	response = post "/nodes/#{vm_info[:node]}/#{vm_info[:type]}/#{vm_id}/status/start", nil
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.start_vm_timeout'
end

#stop_vm(vm_id) ⇒ Object



137
138
139
140
141
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 137

def stop_vm vm_id
	vm_info = get_vm_info vm_id
	response = post "/nodes/#{vm_info[:node]}/#{vm_info[:type]}/#{vm_id}/status/stop", nil
	wait_for_completion task_response: response, timeout_message: 'vagrant_proxmox.errors.stop_vm_timeout'
end

#upload_file(file, content_type: required('content_type'), node: required('node'), storage: required('storage'), replace: false) ⇒ Object



165
166
167
168
169
170
171
172
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 165

def upload_file file, content_type: required('content_type'), node: required('node'), storage: required('storage'), replace: false
	delete_file(filename: file, content_type: content_type, node: node, storage: storage) if replace
	unless is_file_in_storage? filename: file, node: node, storage: storage
		res = post "/nodes/#{node}/storage/#{storage}/upload", content: content_type,
							 filename: File.new(file, 'rb'), node: node, storage: storage
		wait_for_completion task_response: res, timeout_message: 'vagrant_proxmox.errors.upload_timeout'
	end
end

#wait_for_completion(task_response: required('task_response'), timeout_message: required('timeout_message')) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/vagrant-proxmox/proxmox/connection.rb', line 75

def wait_for_completion task_response: required('task_response'), timeout_message: required('timeout_message')
	task_upid = task_response[:data]
	timeout = task_timeout
	task_type = /UPID:.*?:.*?:.*?:.*?:(.*)?:.*?:.*?:/.match(task_upid)[1]
	timeout = imgcopy_timeout if task_type == 'imgcopy'
	begin
		retryable(on: VagrantPlugins::Proxmox::ProxmoxTaskNotFinished,
							tries: timeout / task_status_check_interval + 1,
							sleep: task_status_check_interval) do
			exit_status = get_task_exitstatus task_upid
			exit_status.nil? ? raise(VagrantPlugins::Proxmox::ProxmoxTaskNotFinished) : exit_status
		end
	rescue VagrantPlugins::Proxmox::ProxmoxTaskNotFinished
		raise VagrantPlugins::Proxmox::Errors::Timeout.new timeout_message
	end
end