opennebula 5.12.9 → 6.0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ActionManager.rb +1 -1
- data/lib/CommandManager.rb +1 -1
- data/lib/DriverExecHelper.rb +44 -28
- data/lib/OpenNebulaDriver.rb +8 -4
- data/lib/VirtualMachineDriver.rb +9 -2
- data/lib/cloud/CloudClient.rb +3 -3
- data/lib/datacenter.rb +1257 -0
- data/lib/datastore.rb +1025 -0
- data/lib/distributed_firewall.rb +280 -0
- data/lib/file_helper.rb +370 -0
- data/lib/host.rb +1517 -0
- data/lib/logical_port.rb +50 -0
- data/lib/logical_switch.rb +77 -0
- data/lib/memoize.rb +74 -0
- data/lib/models.rb +32 -0
- data/lib/models/role.rb +1126 -0
- data/lib/models/service.rb +709 -0
- data/lib/network.rb +699 -0
- data/lib/nsx_client.rb +144 -0
- data/lib/nsx_component.rb +28 -0
- data/lib/nsx_constants.rb +149 -0
- data/lib/nsx_driver.rb +78 -0
- data/lib/nsx_error.rb +77 -0
- data/lib/nsx_rule.rb +193 -0
- data/lib/nsxt_client.rb +176 -0
- data/lib/nsxt_dfw.rb +196 -0
- data/lib/nsxt_logical_port.rb +94 -0
- data/lib/nsxt_rule.rb +188 -0
- data/lib/nsxt_tz.rb +38 -0
- data/lib/nsxv_client.rb +176 -0
- data/lib/nsxv_dfw.rb +202 -0
- data/lib/nsxv_logical_port.rb +107 -0
- data/lib/nsxv_rule.rb +172 -0
- data/lib/nsxv_tz.rb +41 -0
- data/lib/opaque_network.rb +134 -0
- data/lib/opennebula.rb +5 -2
- data/lib/opennebula/acl.rb +1 -1
- data/lib/opennebula/acl_pool.rb +1 -1
- data/lib/opennebula/client.rb +10 -2
- data/lib/opennebula/cluster.rb +1 -1
- data/lib/opennebula/cluster_pool.rb +1 -1
- data/lib/opennebula/datastore.rb +1 -1
- data/lib/opennebula/datastore_pool.rb +1 -1
- data/lib/opennebula/document.rb +8 -29
- data/lib/opennebula/document_json.rb +42 -12
- data/lib/opennebula/document_pool.rb +1 -1
- data/lib/opennebula/document_pool_json.rb +1 -1
- data/lib/opennebula/error.rb +4 -1
- data/lib/opennebula/flow.rb +23 -0
- data/lib/opennebula/flow/grammar.rb +1195 -0
- data/lib/opennebula/flow/service_pool.rb +190 -0
- data/lib/opennebula/flow/service_template.rb +608 -0
- data/lib/opennebula/flow/service_template_ext.rb +84 -0
- data/lib/opennebula/flow/service_template_pool.rb +32 -0
- data/lib/opennebula/flow/validator.rb +499 -0
- data/lib/opennebula/group.rb +1 -1
- data/lib/opennebula/group_pool.rb +1 -1
- data/lib/opennebula/hook.rb +5 -12
- data/lib/opennebula/hook_log.rb +1 -1
- data/lib/opennebula/hook_pool.rb +1 -1
- data/lib/opennebula/host.rb +1 -1
- data/lib/opennebula/host_pool.rb +1 -1
- data/lib/opennebula/image.rb +19 -14
- data/lib/opennebula/image_pool.rb +1 -1
- data/lib/opennebula/ldap_auth.rb +1 -1
- data/lib/opennebula/ldap_auth_spec.rb +1 -1
- data/lib/opennebula/lockable_ext.rb +163 -0
- data/lib/opennebula/marketplace.rb +1 -1
- data/lib/opennebula/marketplace_pool.rb +1 -1
- data/lib/opennebula/marketplaceapp.rb +9 -119
- data/lib/opennebula/marketplaceapp_ext.rb +586 -0
- data/lib/opennebula/marketplaceapp_pool.rb +1 -1
- data/lib/opennebula/oneflow_client.rb +4 -3
- data/lib/opennebula/pool.rb +6 -3
- data/lib/opennebula/pool_element.rb +1 -1
- data/lib/opennebula/security_group.rb +1 -1
- data/lib/opennebula/security_group_pool.rb +1 -1
- data/lib/opennebula/server_cipher_auth.rb +1 -1
- data/lib/opennebula/server_x509_auth.rb +1 -1
- data/lib/opennebula/ssh_auth.rb +1 -1
- data/lib/opennebula/system.rb +1 -1
- data/lib/opennebula/template.rb +4 -13
- data/lib/opennebula/template_ext.rb +342 -0
- data/lib/opennebula/template_pool.rb +1 -1
- data/lib/opennebula/user.rb +26 -2
- data/lib/opennebula/user_pool.rb +1 -1
- data/lib/opennebula/utils.rb +1 -1
- data/lib/opennebula/vdc.rb +1 -1
- data/lib/opennebula/vdc_pool.rb +1 -1
- data/lib/opennebula/virtual_machine.rb +26 -206
- data/lib/opennebula/virtual_machine_ext.rb +469 -0
- data/lib/opennebula/virtual_machine_pool.rb +1 -1
- data/lib/opennebula/virtual_network.rb +4 -10
- data/lib/opennebula/virtual_network_pool.rb +1 -1
- data/lib/opennebula/virtual_router.rb +4 -12
- data/lib/opennebula/virtual_router_pool.rb +1 -1
- data/lib/opennebula/vm_group.rb +4 -11
- data/lib/opennebula/vm_group_pool.rb +1 -1
- data/lib/opennebula/vntemplate.rb +4 -13
- data/lib/opennebula/vntemplate_pool.rb +1 -1
- data/lib/opennebula/wait_ext.rb +257 -0
- data/lib/opennebula/x509_auth.rb +1 -1
- data/lib/opennebula/xml_element.rb +1 -1
- data/lib/opennebula/xml_pool.rb +1 -1
- data/lib/opennebula/xml_utils.rb +1 -1
- data/lib/opennebula/zone.rb +1 -1
- data/lib/opennebula/zone_pool.rb +1 -1
- data/lib/rest_client.rb +201 -0
- data/lib/scripts_common.rb +183 -0
- data/lib/transport_zone.rb +43 -0
- data/lib/vcenter_driver.rb +13 -12
- data/lib/vcenter_importer.rb +616 -0
- data/lib/vi_client.rb +281 -0
- data/lib/vi_helper.rb +313 -0
- data/lib/virtual_machine.rb +3477 -0
- data/lib/virtual_wire.rb +158 -0
- data/lib/vm_device.rb +80 -0
- data/lib/vm_disk.rb +202 -0
- data/lib/vm_folder.rb +69 -0
- data/lib/vm_helper.rb +30 -0
- data/lib/vm_monitor.rb +303 -0
- data/lib/vm_nic.rb +70 -0
- data/lib/vm_template.rb +1963 -0
- data/lib/vmm_importer.rb +121 -0
- metadata +140 -27
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
data/lib/opennebula/user.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
|
@@ -34,7 +34,9 @@ module OpenNebula
|
|
|
34
34
|
:update => "user.update",
|
|
35
35
|
:chauth => "user.chauth",
|
|
36
36
|
:quota => "user.quota",
|
|
37
|
-
:login => "user.login"
|
|
37
|
+
:login => "user.login",
|
|
38
|
+
:enable => "user.enable",
|
|
39
|
+
:disable => "user.disable"
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
SELF = -1
|
|
@@ -128,6 +130,16 @@ module OpenNebula
|
|
|
128
130
|
super(USER_METHODS[:delete])
|
|
129
131
|
end
|
|
130
132
|
|
|
133
|
+
# Enable the User
|
|
134
|
+
def enable()
|
|
135
|
+
set_enabled(true)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Disable the User
|
|
139
|
+
def disable()
|
|
140
|
+
set_enabled(false)
|
|
141
|
+
end
|
|
142
|
+
|
|
131
143
|
# Changes the password of the given User
|
|
132
144
|
#
|
|
133
145
|
# +password+ String containing the new password
|
|
@@ -230,5 +242,17 @@ module OpenNebula
|
|
|
230
242
|
all_groups = self.retrieve_elements("GROUPS/ID")
|
|
231
243
|
all_groups.collect! {|x| x.to_i}
|
|
232
244
|
end
|
|
245
|
+
|
|
246
|
+
private
|
|
247
|
+
|
|
248
|
+
def set_enabled(enabled)
|
|
249
|
+
return Error.new('ID not defined') if !@pe_id
|
|
250
|
+
|
|
251
|
+
rc = @client.call(USER_METHODS[:enable], @pe_id, enabled)
|
|
252
|
+
rc = nil if !OpenNebula.is_error?(rc)
|
|
253
|
+
|
|
254
|
+
return rc
|
|
255
|
+
end
|
|
256
|
+
|
|
233
257
|
end
|
|
234
258
|
end
|
data/lib/opennebula/user_pool.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
data/lib/opennebula/utils.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
data/lib/opennebula/vdc.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
data/lib/opennebula/vdc_pool.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
|
2
|
-
# Copyright 2002-
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
3
|
# #
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
5
|
# not use this file except in compliance with the License. You may obtain #
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# limitations under the License. #
|
|
15
15
|
#--------------------------------------------------------------------------- #
|
|
16
16
|
|
|
17
|
+
require 'opennebula/lockable_ext'
|
|
17
18
|
require 'opennebula/pool_element'
|
|
18
19
|
|
|
19
20
|
module OpenNebula
|
|
@@ -123,6 +124,9 @@ module OpenNebula
|
|
|
123
124
|
DISK_RESIZE_POWEROFF
|
|
124
125
|
DISK_RESIZE_UNDEPLOYED
|
|
125
126
|
HOTPLUG_NIC_POWEROFF
|
|
127
|
+
HOTPLUG_RESIZE
|
|
128
|
+
HOTPLUG_SAVEAS_UNDEPLOYED
|
|
129
|
+
HOTPLUG_SAVEAS_STOPPED
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
SHORT_VM_STATES={
|
|
@@ -204,7 +208,10 @@ module OpenNebula
|
|
|
204
208
|
"DISK_RESIZE" => "drsz",
|
|
205
209
|
"DISK_RESIZE_POWEROFF" => "drsz",
|
|
206
210
|
"DISK_RESIZE_UNDEPLOYED" => "drsz",
|
|
207
|
-
"HOTPLUG_NIC_POWEROFF" => "hotp"
|
|
211
|
+
"HOTPLUG_NIC_POWEROFF" => "hotp",
|
|
212
|
+
"HOTPLUG_RESIZE" => "hotp",
|
|
213
|
+
"HOTPLUG_SAVEAS_UNDEPLOYED" => "hotp",
|
|
214
|
+
"HOTPLUG_SAVEAS_STOPPED" => "hotp"
|
|
208
215
|
}
|
|
209
216
|
|
|
210
217
|
HISTORY_ACTION=%w{none migrate live-migrate shutdown shutdown-hard
|
|
@@ -271,6 +278,8 @@ module OpenNebula
|
|
|
271
278
|
|
|
272
279
|
# Class constructor
|
|
273
280
|
def initialize(xml, client)
|
|
281
|
+
LockableExt.make_lockable(self, VM_METHODS)
|
|
282
|
+
|
|
274
283
|
super(xml,client)
|
|
275
284
|
end
|
|
276
285
|
|
|
@@ -701,9 +710,9 @@ module OpenNebula
|
|
|
701
710
|
end
|
|
702
711
|
end
|
|
703
712
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
713
|
+
# Changes the attributes of a VM in power off, failure and undeploy
|
|
714
|
+
# states
|
|
715
|
+
# @param new_conf, string describing the new attributes. Each attribute
|
|
707
716
|
# will replace the existing ones or delete it if empty. Attributes that
|
|
708
717
|
# can be updated are: INPUT/{TYPE, BUS}; RAW/{TYPE, DATA, DATA_VMX},
|
|
709
718
|
# OS/{BOOT, BOOTLOADER, ARCH, MACHINE, KERNEL, INITRD},
|
|
@@ -711,20 +720,10 @@ module OpenNebula
|
|
|
711
720
|
# and GRAPHICS/{TYPE, LISTEN, PASSWD, KEYMAP}
|
|
712
721
|
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
|
713
722
|
# otherwise
|
|
714
|
-
|
|
723
|
+
def updateconf(new_conf)
|
|
715
724
|
return call(VM_METHODS[:updateconf], @pe_id, new_conf)
|
|
716
725
|
end
|
|
717
726
|
|
|
718
|
-
# Lock a VM
|
|
719
|
-
def lock(level)
|
|
720
|
-
return call(VM_METHODS[:lock], @pe_id, level)
|
|
721
|
-
end
|
|
722
|
-
|
|
723
|
-
# Unlock a VM
|
|
724
|
-
def unlock()
|
|
725
|
-
return call(VM_METHODS[:unlock], @pe_id)
|
|
726
|
-
end
|
|
727
|
-
|
|
728
727
|
########################################################################
|
|
729
728
|
# Helpers to get VirtualMachine information
|
|
730
729
|
########################################################################
|
|
@@ -771,205 +770,26 @@ module OpenNebula
|
|
|
771
770
|
self['DEPLOY_ID']
|
|
772
771
|
end
|
|
773
772
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
#
|
|
777
|
-
# @param name [String] Name for the new Template
|
|
778
|
-
# @param name [true,false,nil] Optional, true to make the saved images
|
|
779
|
-
# persistent, false make them non-persistent
|
|
780
|
-
#
|
|
781
|
-
# @return [Integer, OpenNebula::Error] the new Template ID in case of
|
|
782
|
-
# success, error otherwise
|
|
783
|
-
REMOVE_VNET_ATTRS = %w{AR_ID BRIDGE CLUSTER_ID IP MAC TARGET NIC_ID
|
|
784
|
-
NETWORK_ID VN_MAD SECURITY_GROUPS VLAN_ID}
|
|
785
|
-
|
|
786
|
-
REMOVE_IMAGE_ATTRS = %w{DEV_PREFIX SOURCE ORIGINAL_SIZE SIZE
|
|
787
|
-
DISK_SNAPSHOT_TOTAL_SIZE DRIVER IMAGE_STATE SAVE CLONE READONLY
|
|
788
|
-
PERSISTENT TARGET ALLOW_ORPHANS CLONE_TARGET CLUSTER_ID DATASTORE
|
|
789
|
-
DATASTORE_ID DISK_ID DISK_TYPE IMAGE_ID IMAGE IMAGE_UNAME IMAGE_UID
|
|
790
|
-
LN_TARGET TM_MAD TYPE OPENNEBULA_MANAGED}
|
|
791
|
-
|
|
792
|
-
def save_as_template(name,description, persistent=nil)
|
|
793
|
-
img_ids = []
|
|
794
|
-
new_tid = nil
|
|
795
|
-
begin
|
|
796
|
-
rc = info()
|
|
797
|
-
raise if OpenNebula.is_error?(rc)
|
|
798
|
-
|
|
799
|
-
tid = self['TEMPLATE/TEMPLATE_ID']
|
|
800
|
-
if tid.nil? || tid.empty?
|
|
801
|
-
rc = Error.new('VM has no template to be saved')
|
|
802
|
-
raise
|
|
803
|
-
end
|
|
804
|
-
|
|
805
|
-
if state_str() != "POWEROFF"
|
|
806
|
-
rc = Error.new("VM state must be POWEROFF, "<<
|
|
807
|
-
"current state is #{state_str()}, #{lcm_state_str()}")
|
|
808
|
-
raise
|
|
809
|
-
end
|
|
810
|
-
|
|
811
|
-
# Clone the source template
|
|
812
|
-
rc = OpenNebula::Template.new_with_id(tid, @client).clone(name)
|
|
813
|
-
raise if OpenNebula.is_error?(rc)
|
|
814
|
-
|
|
815
|
-
new_tid = rc
|
|
816
|
-
|
|
817
|
-
# Replace the original template's capacity with the actual VM values
|
|
818
|
-
replace = ""
|
|
819
|
-
if !description.nil?
|
|
820
|
-
replace << "DESCRIPTION = \"#{description}\"\n"
|
|
821
|
-
end
|
|
822
|
-
cpu = self['TEMPLATE/CPU']
|
|
823
|
-
if !cpu.nil? && !cpu.empty?
|
|
824
|
-
replace << "CPU = #{cpu}\n"
|
|
825
|
-
end
|
|
826
|
-
|
|
827
|
-
vcpu = self['TEMPLATE/VCPU']
|
|
828
|
-
if !vcpu.nil? && !vcpu.empty?
|
|
829
|
-
replace << "VCPU = #{vcpu}\n"
|
|
830
|
-
end
|
|
831
|
-
|
|
832
|
-
mem = self['TEMPLATE/MEMORY']
|
|
833
|
-
if !mem.nil? && !mem.empty?
|
|
834
|
-
replace << "MEMORY = #{mem}\n"
|
|
835
|
-
end
|
|
836
|
-
|
|
837
|
-
self.each('TEMPLATE/DISK') do |disk|
|
|
838
|
-
# While the previous snapshot is still in progress, we wait
|
|
839
|
-
# indefinitely
|
|
840
|
-
rc = info()
|
|
841
|
-
raise if OpenNebula.is_error?(rc)
|
|
842
|
-
|
|
843
|
-
steps = 0
|
|
844
|
-
while lcm_state_str() == "HOTPLUG_SAVEAS_POWEROFF"
|
|
845
|
-
if steps < 30
|
|
846
|
-
sleep 1
|
|
847
|
-
else
|
|
848
|
-
sleep 15
|
|
849
|
-
end
|
|
850
|
-
|
|
851
|
-
rc = info()
|
|
852
|
-
raise if OpenNebula.is_error?(rc)
|
|
853
|
-
|
|
854
|
-
steps += 1
|
|
855
|
-
end
|
|
856
|
-
|
|
857
|
-
# If the VM is not busy with a previous disk snapshot, we wait
|
|
858
|
-
# but this time with a timeout
|
|
859
|
-
rc = wait_state("POWEROFF")
|
|
860
|
-
raise if OpenNebula.is_error?(rc)
|
|
861
|
-
|
|
862
|
-
disk_id = disk["DISK_ID"]
|
|
863
|
-
if disk_id.nil? || disk_id.empty?
|
|
864
|
-
rc = Error.new('The DISK_ID is missing from the VM template')
|
|
865
|
-
raise
|
|
866
|
-
end
|
|
867
|
-
|
|
868
|
-
image_id = disk["IMAGE_ID"]
|
|
869
|
-
opennebula_managed = disk["OPENNEBULA_MANAGED"]
|
|
870
|
-
type = disk["TYPE"]
|
|
871
|
-
|
|
872
|
-
REMOVE_IMAGE_ATTRS.each do |attr|
|
|
873
|
-
disk.delete_element(attr)
|
|
874
|
-
end
|
|
875
|
-
|
|
876
|
-
if !image_id.nil? && !image_id.empty?
|
|
877
|
-
if type == 'CDROM'
|
|
878
|
-
replace << "DISK = [ IMAGE_ID = #{image_id}"
|
|
879
|
-
if opennebula_managed
|
|
880
|
-
replace << ", OPENNEBULA_MANAGED=#{opennebula_managed}"
|
|
881
|
-
end
|
|
882
|
-
replace << " ]\n"
|
|
883
|
-
else
|
|
884
|
-
rc = disk_saveas(disk_id.to_i,"#{name}-disk-#{disk_id}","",-1)
|
|
885
|
-
|
|
886
|
-
raise if OpenNebula.is_error?(rc)
|
|
887
|
-
|
|
888
|
-
if persistent == true
|
|
889
|
-
OpenNebula::Image.new_with_id(rc.to_i, @client).persistent()
|
|
890
|
-
end
|
|
891
|
-
|
|
892
|
-
img_ids << rc.to_i
|
|
893
|
-
|
|
894
|
-
disk_template = disk.template_like_str(".").tr("\n", ",\n")
|
|
895
|
-
|
|
896
|
-
if disk_template.empty?
|
|
897
|
-
replace << "DISK = [ IMAGE_ID = #{rc} ] \n"
|
|
898
|
-
else
|
|
899
|
-
replace << "DISK = [ IMAGE_ID = #{rc}, " <<
|
|
900
|
-
disk_template << " ] \n"
|
|
901
|
-
end
|
|
902
|
-
end
|
|
903
|
-
else
|
|
904
|
-
# Volatile disks cannot be saved, so the definition is copied
|
|
905
|
-
replace << self.template_like_str(
|
|
906
|
-
"TEMPLATE", true, "DISK[DISK_ID=#{disk_id}]") << "\n"
|
|
907
|
-
end
|
|
908
|
-
end
|
|
909
|
-
|
|
910
|
-
self.each('TEMPLATE/NIC') do |nic|
|
|
911
|
-
nic_id = nic["NIC_ID"]
|
|
773
|
+
def wait_state(state, timeout=120)
|
|
774
|
+
require 'opennebula/wait_ext'
|
|
912
775
|
|
|
913
|
-
|
|
914
|
-
rc = Error.new('The NIC_ID is missing from the VM template')
|
|
915
|
-
raise
|
|
916
|
-
end
|
|
776
|
+
extend OpenNebula::WaitExt
|
|
917
777
|
|
|
918
|
-
|
|
919
|
-
# Remove every automatically generated value
|
|
920
|
-
# The vnet will be referenced via NAME + UNAME (if defined)
|
|
921
|
-
nic.delete_element(attr)
|
|
922
|
-
end
|
|
778
|
+
rc = wait2(state, 'LCM_INIT', timeout)
|
|
923
779
|
|
|
924
|
-
|
|
925
|
-
end
|
|
926
|
-
|
|
927
|
-
# Required by the Sunstone Cloud View
|
|
928
|
-
replace << "SAVED_TEMPLATE_ID = #{tid}\n"
|
|
929
|
-
|
|
930
|
-
new_tmpl = OpenNebula::Template.new_with_id(new_tid, @client)
|
|
931
|
-
|
|
932
|
-
rc = new_tmpl.update(replace, true)
|
|
933
|
-
raise if OpenNebula.is_error?(rc)
|
|
934
|
-
|
|
935
|
-
return new_tid
|
|
936
|
-
|
|
937
|
-
rescue
|
|
938
|
-
# Rollback. Delete the template and the images created
|
|
939
|
-
if !new_tid.nil?
|
|
940
|
-
new_tmpl = OpenNebula::Template.new_with_id(new_tid, @client)
|
|
941
|
-
new_tmpl.delete()
|
|
942
|
-
end
|
|
780
|
+
return Error.new("Timeout expired for state #{state}.") unless rc
|
|
943
781
|
|
|
944
|
-
|
|
945
|
-
img = OpenNebula::Image.new_with_id(id, @client)
|
|
946
|
-
img.delete()
|
|
947
|
-
end
|
|
948
|
-
|
|
949
|
-
return rc
|
|
950
|
-
end
|
|
782
|
+
true
|
|
951
783
|
end
|
|
952
784
|
|
|
953
|
-
def
|
|
954
|
-
|
|
955
|
-
lcm_state = ""
|
|
785
|
+
def wait_state2(state, lcm_state, timeout=120)
|
|
786
|
+
extend OpenNebula::WaitExt
|
|
956
787
|
|
|
957
|
-
timeout
|
|
958
|
-
rc = info()
|
|
959
|
-
return rc if OpenNebula.is_error?(rc)
|
|
960
|
-
|
|
961
|
-
vm_state = state_str()
|
|
962
|
-
lcm_state = lcm_state_str()
|
|
963
|
-
|
|
964
|
-
if vm_state == state
|
|
965
|
-
return true
|
|
966
|
-
end
|
|
788
|
+
rc = wait2(state, lcm_state, timeout)
|
|
967
789
|
|
|
968
|
-
|
|
969
|
-
end
|
|
790
|
+
return Error.new("Timeout expired for state #{state}.") unless rc
|
|
970
791
|
|
|
971
|
-
|
|
972
|
-
"VM is in state #{vm_state}, #{lcm_state}")
|
|
792
|
+
true
|
|
973
793
|
end
|
|
974
794
|
|
|
975
795
|
private
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------- #
|
|
2
|
+
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
|
|
3
|
+
# #
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
|
5
|
+
# not use this file except in compliance with the License. You may obtain #
|
|
6
|
+
# a copy of the License at #
|
|
7
|
+
# #
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
|
9
|
+
# #
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software #
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
|
13
|
+
# See the License for the specific language governing permissions and #
|
|
14
|
+
# limitations under the License. #
|
|
15
|
+
#--------------------------------------------------------------------------- #
|
|
16
|
+
|
|
17
|
+
require 'opennebula/template_ext'
|
|
18
|
+
|
|
19
|
+
# Module to decorate VirtualMachine class with additional helpers not directly
|
|
20
|
+
# exposed through the OpenNebula XMLRPC API. The extensions include
|
|
21
|
+
# - mp_import helper that imports a template into a marketplace
|
|
22
|
+
#
|
|
23
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
|
24
|
+
module OpenNebula::VirtualMachineExt
|
|
25
|
+
|
|
26
|
+
def self.extend_object(obj)
|
|
27
|
+
if !obj.is_a?(OpenNebula::VirtualMachine)
|
|
28
|
+
raise StandardError, "Cannot extended #{obj.class} "\
|
|
29
|
+
' with MarketPlaceAppExt'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << obj
|
|
33
|
+
|
|
34
|
+
####################################################################
|
|
35
|
+
# Public extended interface
|
|
36
|
+
####################################################################
|
|
37
|
+
|
|
38
|
+
#-------------------------------------------------------------------
|
|
39
|
+
# Clones the VM's source Template, replacing the disks with live
|
|
40
|
+
# snapshots of the current disks. The VM capacity and NICs are also
|
|
41
|
+
# preserved
|
|
42
|
+
#
|
|
43
|
+
# @param name [String] Name for the new Template
|
|
44
|
+
# @param name [true,false,nil] Optional, true to make the saved
|
|
45
|
+
# images persistent, false make them non-persistent
|
|
46
|
+
#
|
|
47
|
+
# @return [Integer, OpenNebula::Error] the new Template ID in case
|
|
48
|
+
# of success, error otherwise
|
|
49
|
+
#-------------------------------------------------------------------
|
|
50
|
+
REMOVE_VNET_ATTRS = %w[AR_ID BRIDGE CLUSTER_ID IP MAC TARGET NIC_ID
|
|
51
|
+
NETWORK_ID VN_MAD SECURITY_GROUPS VLAN_ID
|
|
52
|
+
BRIDGE_TYPE]
|
|
53
|
+
|
|
54
|
+
REMOVE_IMAGE_ATTRS = %w[DEV_PREFIX SOURCE ORIGINAL_SIZE SIZE
|
|
55
|
+
DISK_SNAPSHOT_TOTAL_SIZE DRIVER IMAGE_STATE
|
|
56
|
+
SAVE CLONE READONLY PERSISTENT TARGET
|
|
57
|
+
ALLOW_ORPHANS CLONE_TARGET CLUSTER_ID
|
|
58
|
+
DATASTORE DATASTORE_ID DISK_ID DISK_TYPE
|
|
59
|
+
IMAGE_ID IMAGE IMAGE_UNAME IMAGE_UID
|
|
60
|
+
LN_TARGET TM_MAD TYPE OPENNEBULA_MANAGED]
|
|
61
|
+
|
|
62
|
+
def save_as_template(name, desc, opts = {})
|
|
63
|
+
opts = {
|
|
64
|
+
:persistent => false,
|
|
65
|
+
:poweroff => false,
|
|
66
|
+
:logger => nil
|
|
67
|
+
}.merge(opts)
|
|
68
|
+
|
|
69
|
+
img_ids = []
|
|
70
|
+
ntid = nil
|
|
71
|
+
logger = opts[:logger]
|
|
72
|
+
poweron = false
|
|
73
|
+
|
|
74
|
+
rc = info
|
|
75
|
+
|
|
76
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
77
|
+
|
|
78
|
+
tid = self['TEMPLATE/TEMPLATE_ID']
|
|
79
|
+
|
|
80
|
+
raise 'VM has no associated template' unless valid?(tid)
|
|
81
|
+
|
|
82
|
+
# --------------------------------------------------------------
|
|
83
|
+
# Check VM state and poweroff it if needed
|
|
84
|
+
# --------------------------------------------------------------
|
|
85
|
+
if state_str != 'POWEROFF'
|
|
86
|
+
raise 'VM must be POWEROFF' unless opts[:poweroff]
|
|
87
|
+
|
|
88
|
+
logger.info 'Powering off VM' if logger
|
|
89
|
+
|
|
90
|
+
poweron = true
|
|
91
|
+
|
|
92
|
+
rc = poweroff
|
|
93
|
+
|
|
94
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# --------------------------------------------------------------
|
|
98
|
+
# Clone the source template
|
|
99
|
+
# --------------------------------------------------------------
|
|
100
|
+
vm_template = OpenNebula::Template.new_with_id(tid, @client)
|
|
101
|
+
|
|
102
|
+
ntid = vm_template.clone(name)
|
|
103
|
+
|
|
104
|
+
raise ntid.message if OpenNebula.is_error?(ntid)
|
|
105
|
+
|
|
106
|
+
# --------------------------------------------------------------
|
|
107
|
+
# Replace the original template's capacity with VM values
|
|
108
|
+
# --------------------------------------------------------------
|
|
109
|
+
cpu = self['TEMPLATE/CPU']
|
|
110
|
+
vcpu = self['TEMPLATE/VCPU']
|
|
111
|
+
mem = self['TEMPLATE/MEMORY']
|
|
112
|
+
|
|
113
|
+
replace = ''
|
|
114
|
+
replace << "DESCRIPTION = \"#{desc}\"\n" if valid?(desc)
|
|
115
|
+
replace << "CPU = #{cpu}\n" if valid?(cpu)
|
|
116
|
+
replace << "VCPU = #{vcpu}\n" if valid?(vcpu)
|
|
117
|
+
replace << "MEMORY = #{mem}\n" if valid?(mem)
|
|
118
|
+
|
|
119
|
+
# --------------------------------------------------------------
|
|
120
|
+
# Process VM DISKs
|
|
121
|
+
# --------------------------------------------------------------
|
|
122
|
+
logger.info 'Processing VM disks' if logger
|
|
123
|
+
|
|
124
|
+
each('TEMPLATE/DISK') do |disk|
|
|
125
|
+
# Wait for any pending operation
|
|
126
|
+
rc = wait_state2('POWEROFF', 'LCM_INIT')
|
|
127
|
+
|
|
128
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
129
|
+
|
|
130
|
+
disk_id = disk['DISK_ID']
|
|
131
|
+
image_id = disk['IMAGE_ID']
|
|
132
|
+
|
|
133
|
+
omng = disk['OPENNEBULA_MANAGED']
|
|
134
|
+
type = disk['TYPE']
|
|
135
|
+
|
|
136
|
+
raise 'Missing DISK_ID' unless valid?(disk_id)
|
|
137
|
+
|
|
138
|
+
REMOVE_IMAGE_ATTRS.each do |attr|
|
|
139
|
+
disk.delete_element(attr)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Volatile disks cannot be saved, copy definition
|
|
143
|
+
if !valid?(image_id)
|
|
144
|
+
logger.info 'Adding volatile disk' if logger
|
|
145
|
+
|
|
146
|
+
disk_str = template_like_str(
|
|
147
|
+
'TEMPLATE',
|
|
148
|
+
true,
|
|
149
|
+
"DISK [ DISK_ID = #{disk_id} ]"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
replace << "#{disk_str}\n"
|
|
153
|
+
|
|
154
|
+
next
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# CDROM disk, copy definition
|
|
158
|
+
if type == 'CDROM'
|
|
159
|
+
logger.info 'Adding CDROM disk' if logger
|
|
160
|
+
|
|
161
|
+
replace << "DISK = [ IMAGE_ID = #{image_id}"
|
|
162
|
+
replace << ", OPENNEBULA_MANAGED=#{omng}" if omng
|
|
163
|
+
replace << " ]\n"
|
|
164
|
+
|
|
165
|
+
next
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Regular disk, saveas it
|
|
169
|
+
logger.info 'Adding and saving regular disk' if logger
|
|
170
|
+
|
|
171
|
+
ndisk_name = "#{name}-disk-#{disk_id}"
|
|
172
|
+
|
|
173
|
+
rc = disk_saveas(disk_id.to_i, ndisk_name, '', -1)
|
|
174
|
+
|
|
175
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
176
|
+
|
|
177
|
+
if opts[:persistent]
|
|
178
|
+
logger.info 'Making disk persistent' if logger
|
|
179
|
+
|
|
180
|
+
nimg = OpenNebula::Image.new_with_id(rc.to_i, @client)
|
|
181
|
+
nimg.persistent
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
img_ids << rc.to_i
|
|
185
|
+
|
|
186
|
+
disk_tmpl = disk.template_like_str('.').tr("\n", ",\n")
|
|
187
|
+
|
|
188
|
+
replace << "DISK = [ IMAGE_ID = #{rc} "
|
|
189
|
+
replace << ", #{disk_tmpl}" unless disk_tmpl.empty?
|
|
190
|
+
replace << " ]\n"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# --------------------------------------------------------------
|
|
194
|
+
# Process VM NICs
|
|
195
|
+
# --------------------------------------------------------------
|
|
196
|
+
logger.info 'Processing VM NICs' if logger
|
|
197
|
+
|
|
198
|
+
each('TEMPLATE/NIC') do |nic|
|
|
199
|
+
nic_id = nic['NIC_ID']
|
|
200
|
+
|
|
201
|
+
raise 'Missing NIC_ID' unless valid?(nic_id)
|
|
202
|
+
|
|
203
|
+
REMOVE_VNET_ATTRS.each do |attr|
|
|
204
|
+
nic.delete_element(attr)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
replace << 'NIC = [ '
|
|
208
|
+
replace << nic.template_like_str('.').tr("\n", ",\n")
|
|
209
|
+
replace << " ] \n"
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# --------------------------------------------------------------
|
|
213
|
+
# Extra. Required by the Sunstone Cloud View
|
|
214
|
+
# --------------------------------------------------------------
|
|
215
|
+
replace << "SAVED_TEMPLATE_ID = #{tid}\n"
|
|
216
|
+
|
|
217
|
+
new_tmpl = OpenNebula::Template.new_with_id(ntid, @client)
|
|
218
|
+
|
|
219
|
+
logger.info 'Updating VM Template' if logger
|
|
220
|
+
|
|
221
|
+
rc = new_tmpl.update(replace, true)
|
|
222
|
+
|
|
223
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
224
|
+
|
|
225
|
+
# --------------------------------------------------------------
|
|
226
|
+
# Resume VM if needed
|
|
227
|
+
# --------------------------------------------------------------
|
|
228
|
+
if poweron
|
|
229
|
+
logger.info 'Powering on VM' if logger
|
|
230
|
+
|
|
231
|
+
rc = wait_state2('POWEROFF', 'LCM_INIT')
|
|
232
|
+
|
|
233
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
234
|
+
|
|
235
|
+
resume
|
|
236
|
+
|
|
237
|
+
rc = wait_state2('ACTIVE', 'RUNNING')
|
|
238
|
+
|
|
239
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
ntid
|
|
243
|
+
rescue StandardError
|
|
244
|
+
# --------------------------------------------------------------
|
|
245
|
+
# Rollback. Delete the template and the images created
|
|
246
|
+
# --------------------------------------------------------------
|
|
247
|
+
if ntid
|
|
248
|
+
ntmpl = OpenNebula::Template.new_with_id(ntid, @client)
|
|
249
|
+
ntmpl.delete
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
img_ids.each do |id|
|
|
253
|
+
img = OpenNebula::Image.new_with_id(id, @client)
|
|
254
|
+
img.delete
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
raise
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
#-------------------------------------------------------------------
|
|
261
|
+
# Backups a VM. TODO Add final description
|
|
262
|
+
# @param keep [Bool]
|
|
263
|
+
# @param logger[Logger]
|
|
264
|
+
# @param binfo[Hash] Oneshot
|
|
265
|
+
#-------------------------------------------------------------------
|
|
266
|
+
def backup(keep = false, logger = nil, binfo = nil)
|
|
267
|
+
# --------------------------------------------------------------
|
|
268
|
+
# Check backup consistency
|
|
269
|
+
# --------------------------------------------------------------
|
|
270
|
+
unless binfo
|
|
271
|
+
rc = info
|
|
272
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
273
|
+
|
|
274
|
+
binfo = backup_info
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
raise 'No backup information' if binfo.nil?
|
|
278
|
+
|
|
279
|
+
raise 'No frequency defined' unless valid?(binfo[:freq])
|
|
280
|
+
|
|
281
|
+
return if Time.now.to_i - binfo[:last].to_i < binfo[:freq].to_i
|
|
282
|
+
|
|
283
|
+
# --------------------------------------------------------------
|
|
284
|
+
# Save VM as new template
|
|
285
|
+
# --------------------------------------------------------------
|
|
286
|
+
logger.info 'Saving VM as template' if logger
|
|
287
|
+
|
|
288
|
+
tid = save_as_template(
|
|
289
|
+
binfo[:name], '', :poweroff => true, :logger => logger
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
tmp = OpenNebula::Template.new_with_id(tid, @client)
|
|
293
|
+
rc = tmp.info
|
|
294
|
+
|
|
295
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
296
|
+
|
|
297
|
+
# --------------------------------------------------------------
|
|
298
|
+
# Import template into Marketplace & update VM info
|
|
299
|
+
# --------------------------------------------------------------
|
|
300
|
+
logger.info "Importing template #{tmp.id} to marketplace "\
|
|
301
|
+
"#{binfo[:market]}" if logger
|
|
302
|
+
|
|
303
|
+
tmp.extend(OpenNebula::TemplateExt)
|
|
304
|
+
|
|
305
|
+
rc, ids = tmp.mp_import(binfo[:market], true, binfo[:name],
|
|
306
|
+
:wait => true, :logger => logger)
|
|
307
|
+
|
|
308
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
|
309
|
+
|
|
310
|
+
logger.info "Imported app ids: #{ids.join(',')}" if logger
|
|
311
|
+
|
|
312
|
+
rc = update(backup_attr(binfo, ids), true)
|
|
313
|
+
|
|
314
|
+
if OpenNebula.is_error?(rc)
|
|
315
|
+
raise 'Could not update the backup reference: ' \
|
|
316
|
+
" #{rc.message}. New backup ids are #{ids.join(',')}."
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# --------------------------------------------------------------
|
|
320
|
+
# Cleanup
|
|
321
|
+
# --------------------------------------------------------------
|
|
322
|
+
logger.info "Deleting template #{tmp.id}" if logger
|
|
323
|
+
|
|
324
|
+
tmp.delete(true)
|
|
325
|
+
|
|
326
|
+
binfo[:apps].each do |id|
|
|
327
|
+
logger.info "Deleting applicance #{id}" if logger
|
|
328
|
+
|
|
329
|
+
papp = OpenNebula::MarketPlaceApp.new_with_id(id, @client)
|
|
330
|
+
|
|
331
|
+
papp.delete
|
|
332
|
+
end if !keep && binfo[:apps]
|
|
333
|
+
rescue Error, StandardError => e
|
|
334
|
+
logger.fatal(e.inspect) if logger
|
|
335
|
+
raise
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
#-------------------------------------------------------------------
|
|
339
|
+
# Restores VM information from previous backup
|
|
340
|
+
#
|
|
341
|
+
# @param datastore [Integer] Datastore ID to import app backup
|
|
342
|
+
# @param logger [Logger] Logger instance to print debug info
|
|
343
|
+
#
|
|
344
|
+
# @return [Integer] VM ID
|
|
345
|
+
#-------------------------------------------------------------------
|
|
346
|
+
def restore(datastore, logger = nil)
|
|
347
|
+
rc = info
|
|
348
|
+
|
|
349
|
+
if OpenNebula.is_error?(rc)
|
|
350
|
+
raise "Error getting VM: #{rc.message}"
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
logger.info 'Reading backup information' if logger
|
|
354
|
+
|
|
355
|
+
backup_ids = backup_info[:apps]
|
|
356
|
+
|
|
357
|
+
# highest (=last) of the app ids is the template id
|
|
358
|
+
app_id = backup_ids.last
|
|
359
|
+
|
|
360
|
+
app = OpenNebula::MarketPlaceApp.new_with_id(app_id, @client)
|
|
361
|
+
rc = app.info
|
|
362
|
+
|
|
363
|
+
if OpenNebula.is_error?(rc)
|
|
364
|
+
raise "Can not find appliance #{app_id}: #{rc.message}."
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
if logger
|
|
368
|
+
logger.info "Restoring VM #{self['ID']} from " \
|
|
369
|
+
"saved appliance #{app_id}"
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
app.extend(OpenNebula::MarketPlaceAppExt)
|
|
373
|
+
|
|
374
|
+
exp = app.export(:dsid => Integer(datastore),
|
|
375
|
+
:name => "#{self['NAME']} - RESTORED")
|
|
376
|
+
|
|
377
|
+
if OpenNebula.is_error?(exp)
|
|
378
|
+
raise "Can not restore app: #{exp.message}."
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Check possible errors when exporting apps
|
|
382
|
+
exp[:image].each do |image|
|
|
383
|
+
next unless OpenNebula.is_error?(image)
|
|
384
|
+
|
|
385
|
+
raise "Error restoring image: #{image.message}."
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
template = exp[:vmtemplate].first
|
|
389
|
+
|
|
390
|
+
if OpenNebula.is_error?(template)
|
|
391
|
+
raise "Error restoring template: #{template.message}."
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
if logger
|
|
395
|
+
logger.info(
|
|
396
|
+
"Backup restored, VM template: #{exp[:vmtemplate]}, " \
|
|
397
|
+
"images: #{exp[:image]}"
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
logger.info(
|
|
401
|
+
"Instantiating the template #{exp[:vmtemplate]}"
|
|
402
|
+
)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
tmpl = OpenNebula::Template.new_with_id(template, @client)
|
|
406
|
+
rc = tmpl.instantiate
|
|
407
|
+
|
|
408
|
+
if OpenNebula.is_error?(rc)
|
|
409
|
+
raise "Can not instantiate the template: #{rc.message}."
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
rc
|
|
413
|
+
rescue Error, StandardError => e
|
|
414
|
+
logger.fatal(e.inspect) if logger
|
|
415
|
+
raise
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
####################################################################
|
|
419
|
+
# Private extended interface
|
|
420
|
+
####################################################################
|
|
421
|
+
|
|
422
|
+
private
|
|
423
|
+
|
|
424
|
+
# --------------------------------------------------------------
|
|
425
|
+
# Check an attribute is defined and valid
|
|
426
|
+
# --------------------------------------------------------------
|
|
427
|
+
def valid?(att)
|
|
428
|
+
return false if att.nil?
|
|
429
|
+
|
|
430
|
+
return !att.nil? && !att.empty? if att.is_a? String
|
|
431
|
+
|
|
432
|
+
!att.nil?
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
#-------------------------------------------------------------------
|
|
436
|
+
# Get backup information from the VM
|
|
437
|
+
#-------------------------------------------------------------------
|
|
438
|
+
def backup_info
|
|
439
|
+
base = '//USER_TEMPLATE/BACKUP'
|
|
440
|
+
binfo = {}
|
|
441
|
+
|
|
442
|
+
app_ids = self["#{base}/MARKETPLACE_APP_IDS"] || ''
|
|
443
|
+
|
|
444
|
+
binfo[:name] = "#{self['NAME']} - BACKUP " \
|
|
445
|
+
" - #{Time.now.strftime('%Y%m%d_%k%M')}"
|
|
446
|
+
|
|
447
|
+
binfo[:freq] = self["#{base}/FREQUENCY_SECONDS"]
|
|
448
|
+
binfo[:last] = self["#{base}/LAST_BACKUP_TIME"]
|
|
449
|
+
binfo[:market] = Integer(self["#{base}/MARKETPLACE_ID"])
|
|
450
|
+
binfo[:apps] = app_ids.split(',')
|
|
451
|
+
|
|
452
|
+
binfo
|
|
453
|
+
rescue StandardError
|
|
454
|
+
binfo
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def backup_attr(binfo, ids)
|
|
458
|
+
'BACKUP=[' \
|
|
459
|
+
" MARKETPLACE_APP_IDS = \"#{ids.join(',')}\"," \
|
|
460
|
+
" FREQUENCY_SECONDS = \"#{binfo[:freq]}\"," \
|
|
461
|
+
" LAST_BACKUP_TIME = \"#{Time.now.to_i}\"," \
|
|
462
|
+
" MARKETPLACE_ID = \"#{binfo[:market]}\" ]"
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
end
|
|
469
|
+
# rubocop:enable Style/ClassAndModuleChildren
|