# frozen_string_literal: true # Copyright 2018 Tristan Robert # This file is part of ForemanFogProxmox. # ForemanFogProxmox 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. # ForemanFogProxmox 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 ForemanFogProxmox. If not, see . require 'fog/proxmox/helpers/nic_helper' require 'fog/proxmox/helpers/disk_helper' require 'foreman_fog_proxmox/value' module ForemanFogProxmox class Proxmox < ComputeResource include ProxmoxVmHelper include ProxmoxConnection include ProxmoxVmNew include ProxmoxVmCommands include ProxmoxVmQueries include ProxmoxComputeAttributes include ProxmoxVolumes include ProxmoxInterfaces include ProxmoxImages include ProxmoxOperatingSystems include ProxmoxVersion include ProxmoxConsole validates :url, :format => { :with => URI::DEFAULT_PARSER.make_regexp }, :presence => true validates :auth_method, :presence => true, :inclusion => { in: ['access_ticket', 'user_token'], message: ->(value) do format('%s is not a valid authentication method', { value: value }) end } validates :user, :format => { :with => /(\w+)@{1}(\w+)/ }, :presence => true validates :password, :presence => true, :if => :access_ticket? validates :token_id, :presence => true, :if => :user_token? validates :token, :presence => true, :if => :user_token? def provided_attributes super.merge( :mac => :mac ) end def self.provider_friendly_name 'Proxmox' end def capabilities [:build, :new_volume, :new_interface, :image] end def self.model_name ComputeResource.model_name end def associated_host(vm) associate_by('mac', vm.mac) end def associate_by(name, attributes) Host.authorized(:view_hosts, Host).joins(:primary_interface).where(:nics => { :primary => true }).where("nics.#{name}".downcase => attributes.downcase).readonly(false).first end def ssl_certs attrs[:ssl_certs] end def ssl_certs=(value) attrs[:ssl_certs] = value end def certs_to_store return if ssl_certs.blank? store = OpenSSL::X509::Store.new ssl_certs.split(/(?=-----BEGIN)/).each do |cert| x509_cert = OpenSSL::X509::Certificate.new cert store.add_cert x509_cert end store rescue StandardError => e logger.error(e) raise ::Foreman::Exception, N_('Unable to store X509 certificates') end def ssl_verify_peer attrs[:ssl_verify_peer].blank? ? false : Foreman::Cast.to_bool(attrs[:ssl_verify_peer]) end def ssl_verify_peer=(value) attrs[:ssl_verify_peer] = value end def auth_method attrs[:auth_method] || 'access_ticket' end def auth_method=(value) attrs[:auth_method] = value end def token_id attrs[:token_id] end def token_id=(value) attrs[:token_id] = value end def token attrs[:token] end def token=(value) attrs[:token] = value end private def fog_credentials hash = { proxmox_url: url, proxmox_auth_method: auth_method || 'access_ticket', connection_options: connection_options, } if access_ticket? hash[:proxmox_username] = user hash[:proxmox_password] = password end if user_token? hash[:proxmox_userid] = user hash[:proxmox_token] = token hash[:proxmox_tokenid] = token_id end hash end def token_expired?(e) e.response.reason_phrase == 'token expired' end def client @client ||= ::Fog::Proxmox::Compute.new(fog_credentials) rescue Excon::Errors::Unauthorized => e raise ::Foreman::Exception, 'User token expired' if token_expired?(e) rescue StandardError => e logger.warn("failed to create compute client: #{e}") raise e end def identity_client @identity_client ||= ::Fog::Proxmox::Identity.new(fog_credentials) rescue Excon::Errors::Unauthorized => e raise ::Foreman::Exception, 'User token expired' if token_expired?(e) rescue StandardError => e logger.warn("failed to create identity client: #{e}") raise e end def network_client @network_client ||= ::Fog::Proxmox::Network.new(fog_credentials) rescue Excon::Errors::Unauthorized => e raise ::Foreman::Exception, 'User token expired' if token_expired?(e) rescue StandardError => e logger.warn("failed to create network client: #{e}") raise e end def host URI.parse(url).host end end end