diff --git a/include/VirtualMachinePCI.h b/include/VirtualMachinePCI.h deleted file mode 100644 index cc7557c80c..0000000000 --- a/include/VirtualMachinePCI.h +++ /dev/null @@ -1,246 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ -/* not use this file except in compliance with the License. You may obtain */ -/* a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ -/* See the License for the specific language governing permissions and */ -/* limitations under the License. */ -/* -------------------------------------------------------------------------- */ - -#ifndef VIRTUAL_MACHINE_PCI_H_ -#define VIRTUAL_MACHINE_PCI_H_ - -#include "VirtualMachineAttribute.h" -#include "PoolObjectSQL.h" - -class AuthRequest; - -/** - * The VirtualMachine PCI attribute - */ -class VirtualMachinePCI : public VirtualMachineAttribute -{ -public: - VirtualMachinePCI(VectorAttribute *va, int id): - VirtualMachineAttribute(va, id){}; - - virtual ~VirtualMachinePCI(){}; - - /* ---------------------------------------------------------------------- */ - /* PCI get/set functions for boolean disk flags */ - /* ATTACH */ - /* ---------------------------------------------------------------------- */ - void set_attach() - { - set_flag("ATTACH"); - }; - - /* ---------------------------------------------------------------------- */ - /* PCI attributes */ - /* ---------------------------------------------------------------------- */ - /** - * Return the disk id ("PCI_ID") - */ - int get_pci_id() const - { - return get_id(); - } - - /** - * Check if a nic is alias or not - */ - bool is_alias() const - { - return name() == "NIC_ALIAS"; - } - - /** - * Check if a nic is a PCI - */ - bool is_nic() const - { - std::string type; - - if (vector_value("TYPE", type) != 0) - { - return false; - } - - one_util::toupper(type); - - return type == "NIC"; - } - -}; - - -/** - * Set of VirtualMachine NIC - */ -class VirtualMachinePCIs : public VirtualMachineAttributeSet -{ -public: - /* ---------------------------------------------------------------------- */ - /* Constructor and Initialization functions */ - /* ---------------------------------------------------------------------- */ - /** - * Creates the VirtualMachinePCI set from a Template with PCI=[...] - * attributes - * @param tmpl template with PCI - * @param has_id to use the ID's in PCI=[PCI_ID=...] or autogenerate - */ - VirtualMachinePCIs(Template * tmpl): - VirtualMachineAttributeSet(false) - { - std::vector pcis; - - tmpl->get(PCI_NAME, pcis); - - for (auto it = pcis.begin(); it != pcis.end(); ) - { - if ( (*it)->vector_value("TYPE") != "NIC" ) - { - it = pcis.erase(it); - } - else - { - ++it; - } - } - - init(pcis, false); - }; - - /** - * Creates the VirtualMachineNic set from a vector of NIC VectorAttribute - * @param va vector of NIC VectorAttribute - * @param has_id to use the ID's in NIC=[NIC_ID=...] or autogenerate - * @param dispose true to delete the VectorAttributes when the set is - * destroyed - */ - VirtualMachinePCIs(std::vector& va, bool has_id, bool dispose): - VirtualMachineAttributeSet(dispose) - { - init(va, has_id); - }; - - /** - * Creates an empty nic set - */ - VirtualMachinePCIs(bool dispose): - VirtualMachineAttributeSet(dispose){}; - - virtual ~VirtualMachinePCIs(){}; - - /** - * Function used to initialize the attribute map based on a vector of NIC - */ - void init(std::vector& vas, bool has_id) - { - if ( has_id ) - { - init_attribute_map(PCI_ID_NAME, vas); - } - else - { - init_attribute_map("", vas); - } - } - - /* ---------------------------------------------------------------------- */ - /* Iterators */ - /* ---------------------------------------------------------------------- */ - /** - * Generic iterator for the nic set. - */ - class PCIIterator : public AttributeIterator - { - public: - PCIIterator():AttributeIterator(){}; - PCIIterator(const AttributeIterator& dit):AttributeIterator(dit){}; - virtual ~PCIIterator(){}; - - VirtualMachinePCI * operator*() const - { - return static_cast(map_it->second); - } - }; - - PCIIterator begin() - { - PCIIterator it(ExtendedAttributeSet::begin()); - return it; - } - - PCIIterator end() - { - PCIIterator it(ExtendedAttributeSet::end()); - return it; - } - - typedef class PCIIterator pci_iterator; - - /* ---------------------------------------------------------------------- */ - /* NIC interface */ - /* ---------------------------------------------------------------------- */ - /** - * Returns the PCI attribute for a network interface - * @param pci_id of the PCI - * @return pointer to the attribute ir null if not found - */ - VirtualMachinePCI * get_pci(int pci_id) const - { - return static_cast(get_attribute(pci_id)); - } - - /* ---------------------------------------------------------------------- */ - /* Attach PCI interface */ - /* ---------------------------------------------------------------------- */ - /** - * Clear attach status from the attach PCI (ATTACH=YES) and removes PCI - * from the set - */ - VirtualMachinePCI * delete_attach() - { - return static_cast(remove_attribute("ATTACH")); - } - - /** - * Clear attach status from the attach PCI (ATTACH=YES) - */ - VirtualMachinePCI * clear_attach() - { - return static_cast(clear_flag("ATTACH")); - } - - /** - * Get the attach PCI (ATTACH=YES) - */ - VirtualMachinePCI * get_attach() - { - return static_cast(get_attribute("ATTACH")); - } - -protected: - - VirtualMachineAttribute * attribute_factory(VectorAttribute * va, - int id) const - { - return new VirtualMachinePCI(va, id); - }; - -private: - static const char * PCI_NAME; //"PCI" - - static const char * PCI_ID_NAME; //"PCI_ID" -}; - -#endif /*VIRTUAL_MACHINE_PCI_H_*/ - diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 89febb34f7..42477f4ed4 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -2952,8 +2952,6 @@ int DispatchManager::resize(int vid, float cpu, int vcpu, long memory, break; } - auto vmm = Nebula::instance().get_vmm(); - if (!vmm->is_live_resize(vm->get_vmm_mad())) { rc = -1; @@ -3019,8 +3017,6 @@ int DispatchManager::resize(int vid, float cpu, int vcpu, long memory, int DispatchManager::attach_pci(int vid, VectorAttribute * pci, const RequestAttributes& ra, string& error_str) { - ostringstream oss; - auto vm = vmpool->get(vid); if ( vm == nullptr ) @@ -3097,8 +3093,6 @@ int DispatchManager::attach_pci(int vid, VectorAttribute * pci, int DispatchManager::detach_pci(int vid, int pci_id, const RequestAttributes& ra, string& error_str) { - ostringstream oss; - auto vm = vmpool->get(vid); if ( vm == nullptr ) diff --git a/src/oca/go/src/goca/vm.go b/src/oca/go/src/goca/vm.go index faf0f6c41b..6cc1271db6 100644 --- a/src/oca/go/src/goca/vm.go +++ b/src/oca/go/src/goca/vm.go @@ -1001,6 +1001,28 @@ func (vc *VMController) DetachSGContext(ctx context.Context, nicID int, sgID int return err } +// AttachPCI attaches new PCI to Virtual Machine +func (vc *VMController) AttachPCI(pciTemplate string) error { + return vc.AttachPCIContext(context.Background(), pciTemplate) +} + +// AttachSGContext attaches new Security Group to Virtual Machine NIC +func (vc *VMController) AttachPCIContext(ctx context.Context, pciTemplate string) error { + _, err := vc.c.Client.CallContext(ctx, "one.vm.attachpci", vc.ID, pciTemplate) + return err +} + +// DetachPCI detaches a PCI from Virtual Machine +func (vc *VMController) DetachPCI(pciID int) error { + return vc.DetachPCIContext(context.Background(), pciID) +} + +// DetachPCIContext detaches a PCI from Virtual Machine +func (vc *VMController) DetachPCIContext(ctx context.Context, pciID int) error { + _, err := vc.c.Client.CallContext(ctx, "one.vm.detachpci", vc.ID, pciID) + return err +} + // Backup Virtual Machine func (vc *VMController) Backup(dsID int, reset bool) error { return vc.BackupContext(context.Background(), dsID, reset) diff --git a/src/oca/go/src/goca/vm_test.go b/src/oca/go/src/goca/vm_test.go index 322c7eaadd..9f4000ac32 100644 --- a/src/oca/go/src/goca/vm_test.go +++ b/src/oca/go/src/goca/vm_test.go @@ -21,6 +21,7 @@ package goca import ( "testing" "strconv" + "regexp" ds "github.com/OpenNebula/one/src/oca/go/src/goca/schemas/datastore" dskeys "github.com/OpenNebula/one/src/oca/go/src/goca/schemas/datastore/keys" @@ -318,6 +319,43 @@ func (s *VMSuite) TestVMNicSgAttachDetach(c *C) { c.Assert(WaitResource(VMExpectState(c, s.vmID, "ACTIVE", "RUNNING")), Equals, true) } +func (s *VMSuite) TestVMPciAttachDetach(c *C) { + // Deploy VM + vmC := testCtrl.VM(s.vmID) + err := vmC.Deploy(s.hostID, false, -1) + c.Assert(err, IsNil) + c.Assert(WaitResource(VMExpectState(c, s.vmID, "ACTIVE", "RUNNING")), Equals, true) + + err = vmC.Poweroff() + c.Assert(err, IsNil) + c.Assert(WaitResource(VMExpectState(c, s.vmID, "POWEROFF", "")), Equals, true) + + // Attach PCI + err = vmC.AttachPCI("PCI = [ DEVICE = 0863 ]") + c.Assert(err, IsNil) + + // Check PCI exists + vm, err := vmC.Info(false) + c.Assert(err, IsNil) + + pci, err := vm.Template.GetVector("PCI") + c.Assert(err, IsNil) + + matched, _ := regexp.MatchString("DEVICE=\"0863\"", pci.String()) + c.Assert(matched, Equals, true) + + // Detach PCI + err = vmC.DetachPCI(0) + c.Assert(err, IsNil) + + // Check PCI doesn't exist + vm, err = vmC.Info(false) + c.Assert(err, IsNil) + + _, err = vm.Template.GetVector("PCI") + c.Assert(err, NotNil) +} + func (s *VMSuite) TestVMBackup(c *C) { // Deploy VM vmC := testCtrl.VM(s.vmID) diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index d3abae81cc..99983db9e8 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -62,6 +62,8 @@ public class VirtualMachine extends PoolElement{ private static final String UNLOCK = METHOD_PREFIX + "unlock"; private static final String ATTACHSG = METHOD_PREFIX + "attachsg"; private static final String DETACHSG = METHOD_PREFIX + "detachsg"; + private static final String ATTACHPCI = METHOD_PREFIX + "attachpci"; + private static final String DETACHPCI = METHOD_PREFIX + "detachpci"; private static final String BACKUP = METHOD_PREFIX + "backup"; private static final String BACKUPCANCEL = METHOD_PREFIX + "backupcancel"; @@ -779,6 +781,33 @@ public class VirtualMachine extends PoolElement{ return client.call(DETACHSG, id, nicid, sgid); } + /** + * Attaches a PCI to a VM + * + * @param client XML-RPC Client. + * @param id The Virtual Machine id (vid) of the target instance. + * @param pciTemplate The PCI Template to attach + * @return If an error occurs the error message contains the reason. + */ + public static OneResponse pciAttach(Client client, int id, + String pciTemplate) + { + return client.call(ATTACHPCI, id, pciTemplate); + } + + /** + * Detaches a PCI from a VM + * + * @param client XML-RPC Client. + * @param id The virtual machine id (vid) of the target instance. + * @param pciid The PCI id to detach + * @return If an error occurs the error message contains the reason. + */ + public static OneResponse pciDetach(Client client, int id, int pciid) + { + return client.call(DETACHPCI, id, pciid); + } + /** * Backup Virtual Machine * @@ -1376,6 +1405,28 @@ public class VirtualMachine extends PoolElement{ return sgDetach(client, id, nicid, sgid); } + /** + * Attaches a PCI to a VM + * + * @param pciTemplate The PCI template to attach + * @return If an error occurs the error message contains the reason. + */ + public OneResponse pciAttach(String pciTemplate) + { + return pciAttach(client, id, pciTemplate); + } + + /** + * Detaches a PCI from a VM + * + * @param pciid The PCI id to detach + * @return If an error occurs the error message contains the reason. + */ + public OneResponse pciDetach(int pciid) + { + return pciDetach(client, id, pciid); + } + /** * Backup VM * diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 406e0a3f44..628bcbae36 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -884,7 +884,7 @@ module OpenNebula # Detaches a PCI from a VM # - # @param nic_id [Integer] Id of the PCI to be detached + # @param pci_id [Integer] Id of the PCI to be detached # @return [nil, OpenNebula::Error] nil in case of success, Error # otherwise def pci_detach(pci_id) diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index c12482748c..4bf35f4753 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -4124,32 +4124,8 @@ void VirtualMachineAttachPCI::request_execute( // ------------------------------------------------------------------------- // Authorize the operation, restricted attributes // ------------------------------------------------------------------------- - PoolObjectAuth vm_perms; - - if (auto vm = Nebula::instance().get_vmpool()->get_ro(id)) + if (vm_authorization(id, 0, 0, att, 0, 0, 0) == false) { - vm->get_permissions(vm_perms); - } - else - { - att.resp_id = id; - att.resp_obj = PoolObjectSQL::VM; - - failure_response(NO_EXISTS, att); - return; - } - - AuthRequest ar(att.uid, att.group_ids); - - ar.add_auth(att.auth_op, vm_perms); - - VirtualMachine::set_auth_request(att.uid, ar, &tmpl, true); - - if (UserPool::authorize(ar) == -1) - { - att.resp_msg = ar.message; - - failure_response(AUTHORIZATION, att); return; } @@ -4193,30 +4169,8 @@ void VirtualMachineDetachPCI::request_execute( // ------------------------------------------------------------------------- // Authorize the operation, restricted attributes // ------------------------------------------------------------------------- - PoolObjectAuth vm_perms; - - if (auto vm = Nebula::instance().get_vmpool()->get_ro(id)) + if (vm_authorization(id, 0, 0, att, 0, 0, 0) == false) { - vm->get_permissions(vm_perms); - } - else - { - att.resp_id = id; - att.resp_obj = PoolObjectSQL::VM; - - failure_response(NO_EXISTS, att); - return; - } - - AuthRequest ar(att.uid, att.group_ids); - - ar.add_auth(att.auth_op, vm_perms); - - if (UserPool::authorize(ar) == -1) - { - att.resp_msg = ar.message; - - failure_response(AUTHORIZATION, att); return; }