diff --git a/fog-proxmox.gemspec b/fog-proxmox.gemspec index 9b49ba6..630eac6 100644 --- a/fog-proxmox.gemspec +++ b/fog-proxmox.gemspec @@ -39,7 +39,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'bundler', '~> 2.1' spec.add_development_dependency 'bundler-audit', '~> 0.6' - spec.add_development_dependency 'debase', '~> 0.2.2' + spec.add_development_dependency 'debase', '~> 0.2.5.beta1' spec.add_development_dependency 'debride', '~> 1.8' spec.add_development_dependency 'fasterer', '~> 0.3' spec.add_development_dependency 'fastri', '~> 0.3' diff --git a/lib/fog/proxmox.rb b/lib/fog/proxmox.rb index 3c26983..5229e29 100644 --- a/lib/fog/proxmox.rb +++ b/lib/fog/proxmox.rb @@ -29,6 +29,7 @@ module Proxmox autoload :Core, 'fog/proxmox/core' autoload :Errors, 'fog/proxmox/errors' autoload :Identity, 'fog/proxmox/identity' + autoload :Cluster, 'fog/proxmox/cluster' autoload :Compute, 'fog/proxmox/compute' autoload :Storage, 'fog/proxmox/storage' autoload :Network, 'fog/proxmox/network' @@ -36,6 +37,7 @@ module Proxmox extend Fog::Provider service(:identity, 'Identity') + service(:cluster, 'Cluster') service(:compute, 'Compute') service(:storage, 'Storage') service(:network, 'Network') diff --git a/lib/fog/proxmox/cluster.rb b/lib/fog/proxmox/cluster.rb new file mode 100644 index 0000000..2c2e51e --- /dev/null +++ b/lib/fog/proxmox/cluster.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +# Copyright 2018 Tristan Robert + +# This file is part of Fog::Proxmox. + +# Fog::Proxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Fog::Proxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Fog::Proxmox. If not, see . + +require 'fog/proxmox/core' + +module Fog + module Proxmox + # Proxmox cluster service + class Cluster < Fog::Service + requires :proxmox_url, :proxmox_auth_method + recognizes :proxmox_token, :proxmox_tokenid, :proxmox_userid, :persistent, :proxmox_username, :proxmox_password + + # Models + model_path 'fog/proxmox/cluster/models' + model :resource + collection :resources + + # Requests + request_path 'fog/proxmox/cluster/requests' + + # Manage nodes cluster + request :list_resources + request :get_nextid + + # Mock class + class Mock + attr_reader :config + + def initialize(options = {}) + @proxmox_uri = URI.parse(options[:proxmox_url]) + @proxmox_auth_method = options[:proxmox_auth_method] + @proxmox_tokenid = options[:proxmox_tokenid] + @proxmox_userid = options[:proxmox_userid] + @proxmox_username = options[:proxmox_username] + @proxmox_password = options[:proxmox_password] + @proxmox_token = options[:proxmox_token] + @proxmox_path = @proxmox_uri.path + @config = options + end + end + + # Real class + class Real + include Fog::Proxmox::Core + + def self.not_found_class + Fog::Proxmox::Cluster::NotFound + end + + def config + self + end + + def config_service? + true + end + + private + + def configure(source) + source.instance_variables.each do |v| + instance_variable_set(v, source.instance_variable_get(v)) + end + end + end + end + end +end diff --git a/lib/fog/proxmox/cluster/models/resource.rb b/lib/fog/proxmox/cluster/models/resource.rb new file mode 100644 index 0000000..9769b84 --- /dev/null +++ b/lib/fog/proxmox/cluster/models/resource.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true +# Copyright 2018 Tristan Robert + +# This file is part of Fog::Proxmox. + +# Fog::Proxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Fog::Proxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Fog::Proxmox. If not, see . + +# frozen_string_literal: true + +require 'fog/proxmox/hash' + +module Fog + module Proxmox + class Cluster + # class Disk model + class Resource < Fog::Model + identity :id + + attribute :name + attribute :type + attribute :node + + # generic + attribute :maxdisk + + # vm/lxc specific + attribute :vmid + attribute :status + attribute :uptime + attribute :template + # resources are written in bytes, proxmox displays gibibytes + attribute :maxcpu + attribute :maxmem + + # storage specific + attribute :content + attribute :shared + attribute :storage + + def is_template? + template === 1 + end + + def to_s + Fog::Proxmox::Hash.flatten(attributes) + end + end + end + end +end diff --git a/lib/fog/proxmox/cluster/models/resources.rb b/lib/fog/proxmox/cluster/models/resources.rb new file mode 100644 index 0000000..6948262 --- /dev/null +++ b/lib/fog/proxmox/cluster/models/resources.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +# Copyright 2018 Tristan Robert + +# This file is part of Fog::Proxmox. + +# Fog::Proxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Fog::Proxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Fog::Proxmox. If not, see . + +require 'fog/proxmox/cluster/models/resource' + +module Fog + module Proxmox + class Cluster + # class Disks Collection of disk + class Resources < Fog::Collection + model Fog::Proxmox::Cluster::Resource + + def all + load service.list_resources + end + + def get(id) + all.find { |resource| resource.identity === id } + end + + def by_type(type) + all.select { |resource| resource.type === type } + end + end + end + end +end diff --git a/lib/fog/proxmox/cluster/requests/get_nextid.rb b/lib/fog/proxmox/cluster/requests/get_nextid.rb new file mode 100644 index 0000000..6c81720 --- /dev/null +++ b/lib/fog/proxmox/cluster/requests/get_nextid.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +# Copyright 2018 Tristan Robert + +# This file is part of Fog::Proxmox. + +# Fog::Proxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Fog::Proxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Fog::Proxmox. If not, see . + +module Fog + module Proxmox + class Cluster + # class Real get_nextid request + class Real + def get_nextid(vmid = nil) + query = "vmid=#{vmid}" unless vmid.nil? + request( + expects: [200], + method: 'GET', + path: 'cluster/nextid', + query: query || '' + ) + end + end + + # class Mock get_nextid request + class Mock + def get_nextid(vmid = nil) + return "4002" unless vmid + + vmid.to_s + end + end + end + end +end diff --git a/lib/fog/proxmox/cluster/requests/list_resources.rb b/lib/fog/proxmox/cluster/requests/list_resources.rb new file mode 100644 index 0000000..1231e3a --- /dev/null +++ b/lib/fog/proxmox/cluster/requests/list_resources.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +# Copyright 2018 Tristan Robert + +# This file is part of Fog::Proxmox. + +# Fog::Proxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Fog::Proxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Fog::Proxmox. If not, see . + +module Fog + module Proxmox + class Cluster + # class Real get_vnc request + class Real + def list_resources(resource_type = '') + query = resource_type.blank? ? '' : "type=#{resource_type}" + request( + expects: [200], + method: 'GET', + path: 'cluster/resources', + query: query || '' + ) + end + + def list_qemu_resources + list_vm_resources.select { |vm| vm['type'] == 'qemu' } + end + + def list_lxc_resources + list_vm_resources.select { |vm| vm['type'] == 'lxc' } + end + + def list_vm_resources + list_resources('vm') + end + + def list_storage_resources + list_resources('storage') + end + end + + # class Mock get_vnc request + class Mock + def list_resources(resource_type) + case resource_type + when 'qemu' + list_qemu_resources + when 'lxc' + list_lxc_resources + when 'storage' + list_storage_resources + else + (list_qemu_resources + list_lxc_resources + list_storage_resources) + end + end + + def list_qemu_resources + [ + { + 'node' => 'pve', + 'type' => 'qemu', + 'vmid' => '100' + } + ] + end + + def list_lxc_resources + [ + { + 'node' => 'pve', + 'type' => 'lxc', + 'vmid' => '101' + } + ] + end + + def list_storage_resources # rubocop:disable Metrics/MethodLength + [ + { + 'node' => 'pve', + 'type' => 'storage', + 'storage' => 'local' + }, + { + 'node' => 'pve', + 'type' => 'storage', + 'storage' => 'local' + } + ] + end + end + end + end +end diff --git a/lib/fog/proxmox/compute/models/storage.rb b/lib/fog/proxmox/compute/models/storage.rb index 16423ef..e8618cf 100644 --- a/lib/fog/proxmox/compute/models/storage.rb +++ b/lib/fog/proxmox/compute/models/storage.rb @@ -3,14 +3,6 @@ # This file is part of Fog::Proxmox. -# Fog::Proxmox is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# Copyright 2018 Tristan Robert - -# This file is part of Fog::Proxmox. - # Fog::Proxmox is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or diff --git a/spec/cluster_spec.rb b/spec/cluster_spec.rb new file mode 100644 index 0000000..4c2b041 --- /dev/null +++ b/spec/cluster_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +# Copyright 2018 Tristan Robert + +# This file is part of Fog::Proxmox. + +# Fog::Proxmox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# Fog::Proxmox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Fog::Proxmox. If not, see . + +require 'spec_helper' +require_relative './proxmox_vcr' + +describe Fog::Proxmox::Cluster do + before :all do + @proxmox_vcr = ProxmoxVCR.new( + vcr_directory: 'spec/fixtures/proxmox/cluster', + service_class: Fog::Proxmox::Cluster + ) + @service = @proxmox_vcr.service + @proxmox_url = @proxmox_vcr.url + @username = @proxmox_vcr.username + @password = @proxmox_vcr.password + @tokenid = @proxmox_vcr.tokenid + @token = @proxmox_vcr.token + end + + it 'Manage Clusters' do + VCR.use_cassette('cluster') do + # List all resources + resources = @service.resources.all + _(resources).wont_be_nil + _(resources).wont_be_empty + _(resources.size).must_equal 4 + # List all resources of type qemu + qemu_resources = @service.resources.by_type('qemu') + _(qemu_resources).wont_be_nil + _(qemu_resources).wont_be_empty + _(qemu_resources.size).must_equal 1 + end + end +end diff --git a/spec/fixtures/proxmox/cluster/cluster.yml b/spec/fixtures/proxmox/cluster/cluster.yml new file mode 100644 index 0000000..bcde7ad --- /dev/null +++ b/spec/fixtures/proxmox/cluster/cluster.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: get + uri: https://192.168.56.101:8006/api2/json/cluster/resources + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - fog-core/2.2.3 + Cookie: + - PVEAuthCookie=PVE:root@pam:5FBE5F93::J4UGO/cW6NJLxU0fQy8AnxuJhKDkIa+ZLBLUIxlXYO3Nb1ocZ15jqoPl0EEOQpI2sohhmtGYo9bptqaPPH48rmaNKzIUtHjDAg/c425GgbhkSo2jYVeCWcTTEC+nDskOiMkjdE4HIiFLpk71IMEP93hGWJ4+mnUxOLfHsRDodWdJXoGoBlxiUBu0zirFLXR60i6WCK2oX82nPYXRJbsl4VRLYcOkYXnnfaUxYgOL0veZhKRcAWlVRKQ7/lkdG1iu3XlOvEeynqcT2xHs+Z158zALA+ZzAEQ6GYdvFFKr/xR57Kd8hfOhRumKx5EaDfdeYkZP/8ZVH48tEbTXrOEQHg== + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - max-age=0 + Connection: + - Keep-Alive + Date: + - Wed, 25 Nov 2020 13:43:47 GMT + Pragma: + - no-cache + Server: + - pve-api-daemon/3.0 + Content-Length: + - '209' + Content-Type: + - application/json;charset=UTF-8 + Expires: + - Wed, 25 Nov 2020 13:43:47 GMT + body: + encoding: ASCII-8BIT + string: '{"data":[{"cpu":0.486288911006624,"disk":6172704768,"id":"node/pve","level":"b","maxcpu":32,"maxdisk":773845024768,"maxmem":134936813568,"mem":114900549632,"node":"pve","status":"online","type":"node","uptime":6909898},{"cpu":0.00538129953557645,"disk":1983594496,"diskread":0,"diskwrite":0,"id":"qemu/105","maxcpu":4,"maxdisk":34573647872,"maxmem":17179869184,"mem":0,"name":"test01","netin":0,"netout":0,"node":"pve","status":"stopped","template":0,"type":"qemu","uptime":0,"vmid":100},{"cpu":0.00538129953557645,"disk":1983594496,"diskread":10794659840,"diskwrite":45429886976,"id":"lxc/101","maxcpu":1,"maxdisk":8350298112,"maxmem":2147483648,"mem":116183040,"name":"test02","netin":2258649906,"netout":9957850155,"node":"pve","status":"running","template":0,"type":"lxc","uptime":6907061,"vmid":101},{"content":"vztmpl,iso,backup","disk":5444206592,"id":"storage/pve/local","maxdisk":773845024768,"node":"pve","plugintype":"dir","shared":0,"status":"available","storage":"local","type":"storage"},{"content":"images,rootdir","disk":6525668992656,"id":"storage/pve/storage","maxdisk":31831680352256,"node":"pve","plugintype":"zfspool","shared":0,"status":"available","storage":"storage","type":"storage"}]}' + http_version: + recorded_at: Wed, 25 Nov 2020 13:43:48 GMT +recorded_with: VCR 4.0.0 diff --git a/spec/fixtures/proxmox/cluster/common_auth.yml b/spec/fixtures/proxmox/cluster/common_auth.yml new file mode 100644 index 0000000..e9e1ad4 --- /dev/null +++ b/spec/fixtures/proxmox/cluster/common_auth.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: post + uri: https://192.168.56.101:8006/api2/json/access/ticket + body: + encoding: US-ASCII + string: username=root%40pam&password=proxmox01 + headers: + User-Agent: + - fog-core/2.2.3 + Accept: + - application/json + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - max-age=0 + Connection: + - close, Keep-Alive + Date: + - Wed, 25 Nov 2020 13:43:47 GMT + Pragma: + - no-cache + Server: + - pve-api-daemon/3.0 + Content-Length: + - '1167' + Content-Type: + - application/json;charset=UTF-8 + Expires: + - Wed, 25 Nov 2020 13:43:47 GMT + body: + encoding: ASCII-8BIT + string: '{"data":{"CSRFPreventionToken":"5FBE5F93:tNCo7nHYIIdA46RVo8yPQg9ZcbtzibFl3lhAwDPkSqc","ticket":"PVE:root@pam:5FBE5F93::J4UGO/cW6NJLxU0fQy8AnxuJhKDkIa+ZLBLUIxlXYO3Nb1ocZ15jqoPl0EEOQpI2sohhmtGYo9bptqaPPH48rmaNKzIUtHjDAg/c425GgbhkSo2jYVeCWcTTEC+nDskOiMkjdE4HIiFLpk71IMEP93hGWJ4+mnUxOLfHsRDodWdJXoGoBlxiUBu0zirFLXR60i6WCK2oX82nPYXRJbsl4VRLYcOkYXnnfaUxYgOL0veZhKRcAWlVRKQ7/lkdG1iu3XlOvEeynqcT2xHs+Z158zALA+ZzAEQ6GYdvFFKr/xR57Kd8hfOhRumKx5EaDfdeYkZP/8ZVH48tEbTXrOEQHg==","cap":{"nodes":{"Sys.Console":1,"Sys.Audit":1,"Sys.PowerMgmt":1,"Permissions.Modify":1,"Sys.Modify":1,"Sys.Syslog":1},"access":{"Group.Allocate":1,"Permissions.Modify":1,"User.Modify":1},"dc":{"Sys.Audit":1},"vms":{"VM.Config.HWType":1,"VM.Migrate":1,"VM.Snapshot.Rollback":1,"VM.Config.Memory":1,"VM.Config.Disk":1,"VM.PowerMgmt":1,"VM.Monitor":1,"VM.Backup":1,"VM.Audit":1,"VM.Config.CDROM":1,"VM.Config.Network":1,"Permissions.Modify":1,"VM.Clone":1,"VM.Allocate":1,"VM.Config.CPU":1,"VM.Console":1,"VM.Config.Options":1,"VM.Snapshot":1},"storage":{"Datastore.Allocate":1,"Permissions.Modify":1,"Datastore.Audit":1,"Datastore.AllocateSpace":1,"Datastore.AllocateTemplate":1}},"username":"root@pam"}}' + http_version: + recorded_at: Wed, 25 Nov 2020 13:43:48 GMT +recorded_with: VCR 4.0.0