manageiq-smartstate 0.1.2 → 0.1.3
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/.codeclimate.yml +52 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_cc.yml +5 -0
- data/.rubocop_local.yml +8 -0
- data/lib/MiqVm/miq_azure_vm.rb +43 -20
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackCommon.rb +60 -6
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackInstance.rb +4 -0
- data/lib/disk/modules/AzureBlobDisk.rb +6 -64
- data/lib/disk/modules/AzureDiskCommon.rb +99 -0
- data/lib/disk/modules/AzureManagedDisk.rb +55 -0
- data/lib/disk/modules/MiqLargeFile.rb +4 -15
- data/lib/manageiq/smartstate/version.rb +1 -1
- data/lib/metadata/VmConfig/VmConfig.rb +9 -3
- data/lib/metadata/util/win32/Win32EventLog.rb +1 -2
- data/manageiq-smartstate.gemspec +3 -0
- metadata +51 -4
- data/lib/disk/modules/MiqLargeFileWin32.rb +0 -107
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 440961abf4d2b73adb7b0f459afa62e1d367eb82
|
4
|
+
data.tar.gz: e41b5ed2da90f269b303fcb1a5b56df012f32088
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a457a91e0cda2e54b9b352512062999f12fd0a049cb055692e608520820fbe22e3189b91299edefcabf5d95bccc623662ce946fd333e1dc68659b4b5f1340497
|
7
|
+
data.tar.gz: 8187dbd78395beab1cb7ba6533cb7cbf36d9abc7391cd4333e8a2956bf31b394f7b87b022d2647dd8e9b2a66c121438247cf9b937115536eb2ee1234e2477acb
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
exclude_paths:
|
3
|
+
- ".git/"
|
4
|
+
- "**.xml"
|
5
|
+
- "**.yaml"
|
6
|
+
- "**.yml"
|
7
|
+
- "lib/metadata/linux/test/Packages"
|
8
|
+
- "lib/metadata/linux/test/tc_LinuxUtils.rb"
|
9
|
+
- "locale/"
|
10
|
+
- "spec/"
|
11
|
+
- "test/"
|
12
|
+
- "tools/"
|
13
|
+
- "tmp/"
|
14
|
+
engines:
|
15
|
+
brakeman:
|
16
|
+
# very slow :sad_panda:
|
17
|
+
enabled: false
|
18
|
+
bundler-audit:
|
19
|
+
# requires Gemfile.lock
|
20
|
+
enabled: false
|
21
|
+
csslint:
|
22
|
+
enabled: false
|
23
|
+
duplication:
|
24
|
+
enabled: true
|
25
|
+
config:
|
26
|
+
languages:
|
27
|
+
ruby:
|
28
|
+
mass_threshold: 25
|
29
|
+
javascript:
|
30
|
+
eslint:
|
31
|
+
enabled: false
|
32
|
+
channel: "eslint-3"
|
33
|
+
fixme:
|
34
|
+
# let's enable later
|
35
|
+
enabled: false
|
36
|
+
markdownlint:
|
37
|
+
# let's enable later
|
38
|
+
enabled: false
|
39
|
+
rubocop:
|
40
|
+
enabled: true
|
41
|
+
config: '.rubocop_cc.yml'
|
42
|
+
prepare:
|
43
|
+
fetch:
|
44
|
+
- url: "https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_base.yml"
|
45
|
+
path: ".rubocop_base.yml"
|
46
|
+
- url: "https://raw.githubusercontent.com/ManageIQ/guides/master/.rubocop_cc_base.yml"
|
47
|
+
path: ".rubocop_cc_base.yml"
|
48
|
+
ratings:
|
49
|
+
paths:
|
50
|
+
- Gemfile.lock
|
51
|
+
- "**.rake"
|
52
|
+
- "**.rb"
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.rubocop_cc.yml
ADDED
data/.rubocop_local.yml
ADDED
data/lib/MiqVm/miq_azure_vm.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'MiqVm/MiqVm'
|
2
2
|
require 'disk/modules/AzureBlobDisk'
|
3
|
+
require 'disk/modules/AzureManagedDisk'
|
3
4
|
require 'disk/modules/miq_disk_cache'
|
4
5
|
|
5
6
|
class MiqAzureVm < MiqVm
|
6
7
|
def initialize(azure_handle, args)
|
7
|
-
@azure_handle
|
8
|
-
@uri
|
8
|
+
@azure_handle = azure_handle
|
9
|
+
@uri = nil
|
10
|
+
@snap_name = nil
|
11
|
+
@resource_group = args[:resource_group]
|
9
12
|
|
10
13
|
raise ArgumentError, "MiqAzureVm: missing required arg :name" unless (@name = args[:name])
|
11
14
|
|
@@ -13,7 +16,18 @@ class MiqAzureVm < MiqVm
|
|
13
16
|
@uri = args[:image_uri]
|
14
17
|
elsif args[:resource_group] && args[:name]
|
15
18
|
vm_obj = vm_svc.get(@name, args[:resource_group])
|
16
|
-
|
19
|
+
os_disk = vm_obj.properties.storage_profile.os_disk
|
20
|
+
if vm_obj.managed_disk?
|
21
|
+
#
|
22
|
+
# Use the EVM SNAPSHOT Added by the Provider
|
23
|
+
#
|
24
|
+
@snap_name = os_disk.name + "__EVM__SSA__SNAPSHOT"
|
25
|
+
else
|
26
|
+
#
|
27
|
+
# Non-Managed Disk Snapshot handling will be added here by a separate PR.
|
28
|
+
#
|
29
|
+
@uri = os_disk.vhd.uri
|
30
|
+
end
|
17
31
|
else
|
18
32
|
raise ArgumentError, "MiqAzureVm: missing required args: :image_uri or :resource_group"
|
19
33
|
end
|
@@ -24,13 +38,14 @@ class MiqAzureVm < MiqVm
|
|
24
38
|
def getCfg
|
25
39
|
cfg_hash = {}
|
26
40
|
cfg_hash['displayname'] = @name
|
41
|
+
file_name = @uri ? @uri : @snap_name
|
27
42
|
|
28
|
-
$log.debug
|
43
|
+
$log.debug("MiqAzureVm#getCfg: disk = #{file_name}")
|
29
44
|
|
30
45
|
tag = "scsi0:0"
|
31
46
|
cfg_hash["#{tag}.present"] = "true"
|
32
47
|
cfg_hash["#{tag}.devicetype"] = "disk"
|
33
|
-
cfg_hash["#{tag}.filename"] =
|
48
|
+
cfg_hash["#{tag}.filename"] = file_name
|
34
49
|
|
35
50
|
cfg_hash
|
36
51
|
end
|
@@ -38,30 +53,23 @@ class MiqAzureVm < MiqVm
|
|
38
53
|
def openDisks(diskFiles)
|
39
54
|
p_volumes = []
|
40
55
|
|
41
|
-
$log.debug
|
56
|
+
$log.debug("openDisks: #{diskFiles.size} disk files supplied.")
|
42
57
|
|
43
58
|
#
|
44
59
|
# Build a list of the VM's physical volumes.
|
45
60
|
#
|
46
61
|
diskFiles.each do |dtag, df|
|
47
62
|
$log.debug "openDisks: processing disk file (#{dtag}): #{df}"
|
48
|
-
|
49
|
-
|
50
|
-
dInfo.fileName = df
|
51
|
-
dInfo.hardwareId = dtag
|
52
|
-
disk_format = @vmConfig.getHash["#{dtag}.format"]
|
53
|
-
dInfo.format = disk_format unless disk_format.blank?
|
54
|
-
|
55
|
-
mode = @vmConfig.getHash["#{dtag}.mode"]
|
56
|
-
|
57
|
-
dInfo.hardwareId = dtag
|
58
|
-
dInfo.rawDisk = true
|
63
|
+
d_info = open_disks_info(dtag, df)
|
59
64
|
|
60
65
|
begin
|
61
|
-
|
66
|
+
if @uri
|
67
|
+
d = MiqDiskCache.new(AzureBlobDisk.new(sa_svc, @uri, d_info), 100, 128)
|
68
|
+
else
|
69
|
+
d = MiqDiskCache.new(AzureManagedDisk.new(snap_svc, @snap_name, d_info), 100, 128)
|
70
|
+
end
|
62
71
|
rescue => err
|
63
|
-
$log.error
|
64
|
-
$log.error err.to_s
|
72
|
+
$log.error("#{err}: Couldn't open disk file: #{df}")
|
65
73
|
$log.debug err.backtrace.join("\n")
|
66
74
|
@diskInitErrors[df] = err.to_s
|
67
75
|
next
|
@@ -86,6 +94,17 @@ class MiqAzureVm < MiqVm
|
|
86
94
|
p_volumes
|
87
95
|
end # def openDisks
|
88
96
|
|
97
|
+
def open_disks_info(disk_tag, disk_file)
|
98
|
+
disk_info = OpenStruct.new
|
99
|
+
disk_info.fileName = disk_file
|
100
|
+
disk_info.hardwareId = disk_tag
|
101
|
+
disk_format = @vmConfig.getHash["#{disk_tag}.format"]
|
102
|
+
disk_info.format = disk_format unless disk_format.blank?
|
103
|
+
disk_info.rawDisk = true
|
104
|
+
disk_info.resource_group = @resource_group
|
105
|
+
disk_info
|
106
|
+
end
|
107
|
+
|
89
108
|
def vm_svc
|
90
109
|
@vm_svc ||= Azure::Armrest::VirtualMachineService.new(@azure_handle)
|
91
110
|
end
|
@@ -93,4 +112,8 @@ class MiqAzureVm < MiqVm
|
|
93
112
|
def sa_svc
|
94
113
|
@sa_svc ||= Azure::Armrest::StorageAccountService.new(@azure_handle)
|
95
114
|
end
|
115
|
+
|
116
|
+
def snap_svc
|
117
|
+
@snap_svc ||= Azure::Armrest::Storage::SnapshotService.new(@azure_handle)
|
118
|
+
end
|
96
119
|
end
|
@@ -11,20 +11,23 @@ module MiqOpenStackCommon
|
|
11
11
|
send("disk_format_glance_#{image_service.version}", snapshot_image_id)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def get_image_metadata_snapshot_id(image)
|
15
|
+
image.metadata.each do |m|
|
16
|
+
next if m.key != "block_device_mapping"
|
17
|
+
return m.value[0]['snapshot_id']
|
18
|
+
end
|
19
|
+
end
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
$log.debug "#{log_prefix}: image = #{image.class.name}"
|
21
|
+
def download_image_data_glance_v2(image)
|
22
|
+
log_prefix = "#{self.class.name}##{__method__}"
|
20
23
|
|
24
|
+
image_id = image.id
|
21
25
|
iname = image.name
|
22
26
|
isize = image.size.to_i
|
23
27
|
$log.debug "#{log_prefix}: iname = #{iname}"
|
24
28
|
$log.debug "#{log_prefix}: isize = #{isize}"
|
25
29
|
|
26
30
|
raise "Image: #{iname} (#{image_id}) is empty" unless isize > 0
|
27
|
-
|
28
31
|
tot = 0
|
29
32
|
tf = MiqTempfile.new(iname, :encoding => 'ascii-8bit')
|
30
33
|
$log.debug "#{log_prefix}: saving image to #{tf.path}"
|
@@ -50,6 +53,57 @@ module MiqOpenStackCommon
|
|
50
53
|
end
|
51
54
|
tf
|
52
55
|
end
|
56
|
+
|
57
|
+
def create_image_from_snapshot(snapshot_id, disk_format)
|
58
|
+
snapshot = volume_service.snapshots.get(snapshot_id)
|
59
|
+
volume_options = {
|
60
|
+
:name => "Temp Volume from #{snapshot.name}",
|
61
|
+
:size => snapshot.size,
|
62
|
+
:snapshot_id => snapshot_id
|
63
|
+
}
|
64
|
+
volume = volume_service.volumes.new(volume_options)
|
65
|
+
volume.save
|
66
|
+
begin
|
67
|
+
while volume.status != 'available'
|
68
|
+
sleep(10)
|
69
|
+
volume = volume_service.volumes.get(volume.id)
|
70
|
+
end
|
71
|
+
response = volume_service.action(volume.id, 'os-volume_upload_image' => {
|
72
|
+
:image_name => "Temp Image from #{snapshot.name}",
|
73
|
+
:disk_format => disk_format})
|
74
|
+
image_id = response.body["os-volume_upload_image"]["image_id"]
|
75
|
+
while image_service.images.get(image_id).status.downcase != 'active'
|
76
|
+
sleep(10)
|
77
|
+
end
|
78
|
+
return image_service.images.get(image_id)
|
79
|
+
ensure
|
80
|
+
volume.destroy
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_image_file_glance_v2(image_id)
|
85
|
+
log_prefix = "#{self.class.name}##{__method__}"
|
86
|
+
|
87
|
+
image = image_service.images.get(image_id)
|
88
|
+
raise "Image #{image_id} not found" unless image
|
89
|
+
$log.debug "#{log_prefix}: image = #{image.class.name}"
|
90
|
+
|
91
|
+
if image.size.to_i == 0
|
92
|
+
# try getting image from metadata; oddly the image metadata is only available if
|
93
|
+
# image is queried through compute service
|
94
|
+
unless (snapshot_id = get_image_metadata_snapshot_id(compute_service.images.get(image_id))).nil?
|
95
|
+
temp_image = create_image_from_snapshot(snapshot_id, image.disk_format)
|
96
|
+
begin
|
97
|
+
tf = download_image_data_glance_v2(temp_image)
|
98
|
+
ensure
|
99
|
+
temp_image.destroy
|
100
|
+
end
|
101
|
+
end
|
102
|
+
else
|
103
|
+
tf = download_image_data_glance_v2(image)
|
104
|
+
end
|
105
|
+
tf
|
106
|
+
end
|
53
107
|
|
54
108
|
def get_image_file_glance_v1(image_id)
|
55
109
|
log_prefix = "#{self.class.name}##{__method__}"
|
@@ -28,6 +28,10 @@ class MiqOpenStackInstance
|
|
28
28
|
@image_service ||= @openstack_handle.detect_image_service
|
29
29
|
end
|
30
30
|
|
31
|
+
def volume_service
|
32
|
+
@volume_service ||= @openstack_handle.detect_volume_service
|
33
|
+
end
|
34
|
+
|
31
35
|
def instance
|
32
36
|
@instance ||= compute_service.servers.get(@instance_id)
|
33
37
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require "disk/modules/AzureDiskCommon"
|
1
2
|
require_relative "../MiqDisk"
|
2
3
|
require 'ostruct'
|
3
4
|
|
4
5
|
module AzureBlobDisk
|
6
|
+
include AzureDiskCommon
|
5
7
|
# The maximum read length that supports MD5 return.
|
6
8
|
MAX_READ_LEN = 1024 * 1024 * 4
|
7
9
|
|
@@ -16,50 +18,19 @@ module AzureBlobDisk
|
|
16
18
|
|
17
19
|
def d_init
|
18
20
|
@diskType = "azure-blob"
|
19
|
-
@blockSize =
|
21
|
+
@blockSize = AzureDiskCommon::SECTOR_LENGTH
|
20
22
|
@blob_uri = @dInfo.blob_uri
|
21
23
|
@storage_acct_svc = @dInfo.storage_acct_svc
|
22
|
-
|
23
|
-
uri_info = @storage_acct_svc.parse_uri(@blob_uri)
|
24
|
-
@container = uri_info[:container]
|
25
|
-
@blob = uri_info[:blob]
|
26
|
-
@acct_name = uri_info[:account_name]
|
27
|
-
@snapshot = uri_info[:snapshot]
|
28
|
-
|
29
|
-
@storage_acct = @storage_acct_svc.accounts_by_name[@acct_name]
|
30
|
-
raise "AzureBlob: Storage account #{@acct_name} not found." unless @storage_acct
|
31
|
-
|
32
|
-
$log.debug "AzureBlobDisk: open(#{@blob_uri})"
|
33
|
-
@t0 = Time.now.to_i
|
34
|
-
@reads = 0
|
35
|
-
@bytes = 0
|
36
|
-
@split_reads = 0
|
24
|
+
d_init_common(@dInfo)
|
37
25
|
end
|
38
26
|
|
39
27
|
def d_close
|
40
|
-
|
41
|
-
t1 = Time.now.to_i
|
42
|
-
$log.debug "AzureBlobDisk: close(#{@blob_uri})"
|
43
|
-
$log.debug "AzureBlobDisk: (#{@blob_uri}) time: #{t1 - @t0}"
|
44
|
-
$log.debug "AzureBlobDisk: (#{@blob_uri}) reads: #{@reads}, split_reads: #{@split_reads}"
|
45
|
-
$log.debug "AzureBlobDisk: (#{@blob_uri}) bytes: #{@bytes}"
|
46
|
-
nil
|
28
|
+
d_close_common
|
47
29
|
end
|
48
30
|
|
49
31
|
def d_read(pos, len)
|
50
32
|
$log.debug "AzureBlobDisk#d_read(#{pos}, #{len})"
|
51
|
-
|
52
|
-
|
53
|
-
@split_reads += 1
|
54
|
-
ret = ""
|
55
|
-
blocks, rem = len.divmod(MAX_READ_LEN)
|
56
|
-
|
57
|
-
blocks.times do
|
58
|
-
ret << blob_read(pos, MAX_READ_LEN)
|
59
|
-
end
|
60
|
-
ret << blob_read(pos, rem) if rem > 0
|
61
|
-
|
62
|
-
ret
|
33
|
+
d_read_common(pos, len)
|
63
34
|
end
|
64
35
|
|
65
36
|
def d_size
|
@@ -69,33 +40,4 @@ module AzureBlobDisk
|
|
69
40
|
def d_write(_pos, _buf, _len)
|
70
41
|
raise "Write operation not supported."
|
71
42
|
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def blob_read(start_byte, length)
|
76
|
-
$log.debug "AzureBlobDisk#blob_read(#{start_byte}, #{length})"
|
77
|
-
options = {
|
78
|
-
:start_byte => start_byte,
|
79
|
-
:length => length
|
80
|
-
}
|
81
|
-
options[:date] = @snapshot if @snapshot
|
82
|
-
|
83
|
-
ret = @storage_acct.get_blob_raw(@container, @blob, key, options)
|
84
|
-
|
85
|
-
@reads += 1
|
86
|
-
@bytes += ret.body.length
|
87
|
-
|
88
|
-
ret.body
|
89
|
-
end
|
90
|
-
|
91
|
-
def blob_properties
|
92
|
-
@blob_properties ||= begin
|
93
|
-
options = @snapshot ? {:date => @snapshot} : {}
|
94
|
-
@storage_acct.blob_properties(@container, @blob, key, options)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def key
|
99
|
-
@key ||= @storage_acct_svc.list_account_keys(@storage_acct.name, @storage_acct.resource_group).fetch('key1')
|
100
|
-
end
|
101
43
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require_relative '../MiqDisk'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module AzureDiskCommon
|
5
|
+
# The maximum read length that supports MD5 return.
|
6
|
+
MAX_READ_LEN = 1024 * 1024 * 4
|
7
|
+
SECTOR_LENGTH = 512
|
8
|
+
|
9
|
+
def d_init_common(d_info)
|
10
|
+
@blockSize = SECTOR_LENGTH
|
11
|
+
if d_info.blob_uri
|
12
|
+
d_init_blob_disk(d_info)
|
13
|
+
else
|
14
|
+
d_init_managed_disk(d_info)
|
15
|
+
end
|
16
|
+
$log.debug("#{@class}: open(#{@disk_path})")
|
17
|
+
@t0 = Time.now.to_i
|
18
|
+
@reads = 0
|
19
|
+
@bytes = 0
|
20
|
+
@split_reads = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def d_init_blob_disk(d_info)
|
24
|
+
@blob_uri = d_info.blob_uri
|
25
|
+
@storage_acct_svc = d_info.storage_acct_svc
|
26
|
+
@my_class = "AzureBlobDisk"
|
27
|
+
uri_info = @storage_acct_svc.parse_uri(@blob_uri)
|
28
|
+
@container = uri_info[:container]
|
29
|
+
@blob = uri_info[:blob]
|
30
|
+
@acct_name = uri_info[:account_name]
|
31
|
+
@snapshot = uri_info[:snapshot]
|
32
|
+
@storage_acct = @storage_acct_svc.accounts_by_name[@acct_name]
|
33
|
+
@disk_path = @blob_uri
|
34
|
+
raise "AzureBlob: Storage account #{@acct_name} not found." unless @storage_acct
|
35
|
+
end
|
36
|
+
|
37
|
+
def d_init_managed_disk(d_info)
|
38
|
+
@disk_name = d_info.disk_name
|
39
|
+
@storage_disk_svc = d_info.storage_disk_svc
|
40
|
+
@resource_group = d_info.resource_group
|
41
|
+
@my_class = "AzureManagedDisk"
|
42
|
+
@disk_path = @disk_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def d_close_common
|
46
|
+
return nil unless $log.debug?
|
47
|
+
t1 = Time.now.to_i
|
48
|
+
$log.debug("#{@my_class}: close(#{@disk_path})")
|
49
|
+
$log.debug("#{@my_class}: (#{@disk_path}) time: #{t1 - @t0}")
|
50
|
+
$log.debug("#{@my_class}: (#{@disk_path}) reads: #{@reads}, split_reads: #{@split_reads}")
|
51
|
+
$log.debug("#{@my_class}: (#{@disk_path}) bytes: #{@bytes}")
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def d_read_common(pos, len)
|
56
|
+
return blob_read(pos, len) unless len > MAX_READ_LEN
|
57
|
+
|
58
|
+
@split_reads += 1
|
59
|
+
ret = ""
|
60
|
+
blocks, rem = len.divmod(MAX_READ_LEN)
|
61
|
+
|
62
|
+
blocks.times do
|
63
|
+
ret << blob_read(pos, MAX_READ_LEN)
|
64
|
+
end
|
65
|
+
ret << blob_read(pos, rem) if rem > 0
|
66
|
+
|
67
|
+
ret
|
68
|
+
end
|
69
|
+
|
70
|
+
def blob_properties
|
71
|
+
@blob_properties ||= begin
|
72
|
+
options = @snapshot ? {:date => @snapshot} : {}
|
73
|
+
@storage_acct.blob_properties(@container, @blob, key, options)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def blob_read(start_byte, length)
|
78
|
+
$log.debug("#{@my_class}#blob_read(#{start_byte}, #{length})")
|
79
|
+
options = {
|
80
|
+
:start_byte => start_byte,
|
81
|
+
:length => length
|
82
|
+
}
|
83
|
+
if @storage_acct
|
84
|
+
options[:date] = @snapshot if @snapshot
|
85
|
+
ret = @storage_acct.get_blob_raw(@container, @blob, key, options)
|
86
|
+
else
|
87
|
+
ret = @storage_disk_svc.get_blob_raw(@disk_name, @resource_group, options)
|
88
|
+
end
|
89
|
+
|
90
|
+
@reads += 1
|
91
|
+
@bytes += ret.body.length
|
92
|
+
|
93
|
+
ret.body
|
94
|
+
end
|
95
|
+
|
96
|
+
def key
|
97
|
+
@key ||= @storage_acct_svc.list_account_keys(@storage_acct.name, @storage_acct.resource_group).fetch('key1')
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "disk/modules/AzureDiskCommon"
|
2
|
+
require_relative "../MiqDisk"
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module AzureManagedDisk
|
6
|
+
include AzureDiskCommon
|
7
|
+
def self.new(svc, disk_name, dInfo = nil)
|
8
|
+
d_info = dInfo || OpenStruct.new
|
9
|
+
d_info.storage_disk_svc = svc
|
10
|
+
d_info.disk_name = disk_name
|
11
|
+
d_info.fileName = disk_name
|
12
|
+
|
13
|
+
MiqDisk.new(self, d_info, 0)
|
14
|
+
end
|
15
|
+
|
16
|
+
def d_init
|
17
|
+
@diskType = "azure-managed"
|
18
|
+
@blockSize = SECTOR_LENGTH
|
19
|
+
@disk_name = @dInfo.disk_name
|
20
|
+
@storage_disk_svc = @dInfo.storage_disk_svc
|
21
|
+
@resource_group = @dInfo.resource_group
|
22
|
+
d_init_common(@dInfo)
|
23
|
+
end
|
24
|
+
|
25
|
+
def d_close
|
26
|
+
d_close_common
|
27
|
+
end
|
28
|
+
|
29
|
+
def d_read(pos, len)
|
30
|
+
$log.debug("AzureManagedDisk#d_read(#{pos}, #{len})")
|
31
|
+
d_read_common(pos, len)
|
32
|
+
end
|
33
|
+
|
34
|
+
def d_size
|
35
|
+
@d_size ||= blob_headers[:content_range].split("/")[1].to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
def d_write(_pos, _buf, _len)
|
39
|
+
raise "Write operation not supported."
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def blob_headers
|
45
|
+
$log.debug("AzureManagedDisk#blob_headers")
|
46
|
+
@blob_headers ||= begin
|
47
|
+
options = {
|
48
|
+
:start_byte => 0,
|
49
|
+
:length => 1
|
50
|
+
}
|
51
|
+
data = @storage_disk_svc.get_blob_raw(@disk_name, @resource_group, options)
|
52
|
+
data.headers
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -6,15 +6,11 @@ if Sys::Platform::IMPL == :linux
|
|
6
6
|
require 'linux_block_device'
|
7
7
|
require 'disk/modules/RawBlockIO'
|
8
8
|
end
|
9
|
-
elsif Sys::Platform::OS == :windows
|
10
|
-
require 'disk/modules/MiqLargeFileWin32'
|
11
9
|
end
|
12
10
|
|
13
11
|
module MiqLargeFile
|
14
12
|
def self.open(file_name, flags)
|
15
13
|
case Sys::Platform::OS
|
16
|
-
when :windows
|
17
|
-
return(MiqLargeFileWin32.new(file_name, flags))
|
18
14
|
when :unix
|
19
15
|
if Sys::Platform::IMPL == :linux
|
20
16
|
return(RawBlockIO.new(file_name, flags)) if MiqLargeFileStat.new(file_name).blockdev?
|
@@ -26,17 +22,10 @@ module MiqLargeFile
|
|
26
22
|
end
|
27
23
|
|
28
24
|
def self.size(file_name)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
File.size(file_name)
|
34
|
-
else
|
35
|
-
f = open(file_name, "r")
|
36
|
-
s = f.size
|
37
|
-
f.close
|
38
|
-
return s
|
39
|
-
end
|
25
|
+
f = open(file_name, "r")
|
26
|
+
s = f.size
|
27
|
+
f.close
|
28
|
+
s
|
40
29
|
end
|
41
30
|
|
42
31
|
# For camcorder interposition.
|
@@ -158,8 +158,7 @@ class VmConfig
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def set_vmconfig_path(config_path)
|
161
|
-
|
162
|
-
@configFile = ds.nil? ? File.normalize(config_path) : config_path
|
161
|
+
@configFile = normalize_vmconfig_file(config_path)
|
163
162
|
@configPath = File.dirname(@configFile)
|
164
163
|
end
|
165
164
|
|
@@ -255,6 +254,13 @@ class VmConfig
|
|
255
254
|
|
256
255
|
private
|
257
256
|
|
257
|
+
def normalize_vmconfig_file(config_file)
|
258
|
+
ds, _dir, _name = split_filename(config_file)
|
259
|
+
return config_file unless ds.nil?
|
260
|
+
|
261
|
+
File.expand_path(config_file.tr('\\', '/'))
|
262
|
+
end
|
263
|
+
|
258
264
|
def diskKey?(key)
|
259
265
|
key =~ /^ide\d+:\d+\.filename$/ || key =~ /^scsi\d+:\d+\.filename$/
|
260
266
|
end
|
@@ -446,7 +452,7 @@ class VmConfig
|
|
446
452
|
@files = []
|
447
453
|
if @direct_file_access
|
448
454
|
Dir.glob(File.join(@configPath, "/*.*")) do |f|
|
449
|
-
s = File.
|
455
|
+
s = File.size(f) rescue 0
|
450
456
|
@files << {:path => f, :name => File.basename(f), :size => s, :mtime => File.mtime(f)}
|
451
457
|
end
|
452
458
|
else
|
@@ -13,7 +13,6 @@ require 'metadata/util/win32/peheader'
|
|
13
13
|
require 'metadata/util/win32/remote-registry'
|
14
14
|
|
15
15
|
# Dev needs this.
|
16
|
-
require 'Win32API' if Sys::Platform::OS == :windows
|
17
16
|
require 'metadata/util/win32/system_path_win'
|
18
17
|
|
19
18
|
require 'digest/md5'
|
@@ -149,7 +148,7 @@ class Win32EventLog
|
|
149
148
|
|
150
149
|
# If an MiqFS instance was not passed, then the OS has to be (or emulate) Win32.
|
151
150
|
# If an MiqFS instance *was* passed, then if the guest OS is not Windows then getSystemRoot will throw.
|
152
|
-
raise "#{self.class}::initialize:
|
151
|
+
raise "#{self.class}::initialize: Filesystem is not MiqFS: cannot continue" if !vmMiqFs.class.to_s.include?('Miq')
|
153
152
|
|
154
153
|
# Get a file system instance if we don't already have one.
|
155
154
|
@fs = vmMiqFs
|
data/manageiq-smartstate.gemspec
CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
+
spec.add_dependency "azure-armrest"
|
24
|
+
spec.add_dependency "binary_struct", "~> 2.1"
|
23
25
|
spec.add_dependency "iniparse"
|
24
26
|
spec.add_dependency "linux_block_device", "~>0.2.1"
|
25
27
|
spec.add_dependency "memory_buffer", ">=0.1.0"
|
@@ -33,6 +35,7 @@ Gem::Specification.new do |spec|
|
|
33
35
|
spec.add_development_dependency "vcr", "~>3.0.2"
|
34
36
|
spec.add_development_dependency "webmock", "~>2.3.1"
|
35
37
|
spec.add_development_dependency "simplecov"
|
38
|
+
spec.add_development_dependency "rubocop"
|
36
39
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
|
37
40
|
|
38
41
|
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manageiq-smartstate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Developers
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: azure-armrest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: binary_struct
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.1'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: iniparse
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +206,20 @@ dependencies:
|
|
178
206
|
- - ">="
|
179
207
|
- !ruby/object:Gem::Version
|
180
208
|
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: rubocop
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
181
223
|
- !ruby/object:Gem::Dependency
|
182
224
|
name: codeclimate-test-reporter
|
183
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,9 +240,13 @@ executables: []
|
|
198
240
|
extensions: []
|
199
241
|
extra_rdoc_files: []
|
200
242
|
files:
|
243
|
+
- ".codeclimate.yml"
|
201
244
|
- ".gitignore"
|
202
245
|
- ".rspec"
|
203
246
|
- ".rspec_ci"
|
247
|
+
- ".rubocop.yml"
|
248
|
+
- ".rubocop_cc.yml"
|
249
|
+
- ".rubocop_local.yml"
|
204
250
|
- ".travis.yml"
|
205
251
|
- Gemfile
|
206
252
|
- LICENSE.txt
|
@@ -271,6 +317,8 @@ files:
|
|
271
317
|
- lib/disk/camcorder_test.rb
|
272
318
|
- lib/disk/dos_mbr.img
|
273
319
|
- lib/disk/modules/AzureBlobDisk.rb
|
320
|
+
- lib/disk/modules/AzureDiskCommon.rb
|
321
|
+
- lib/disk/modules/AzureManagedDisk.rb
|
274
322
|
- lib/disk/modules/LocalDevMod.rb
|
275
323
|
- lib/disk/modules/LocalDevProbe.rb
|
276
324
|
- lib/disk/modules/MSCommon.rb
|
@@ -279,7 +327,6 @@ files:
|
|
279
327
|
- lib/disk/modules/MSVSDynamicDisk.rb
|
280
328
|
- lib/disk/modules/MSVSFixedDisk.rb
|
281
329
|
- lib/disk/modules/MiqLargeFile.rb
|
282
|
-
- lib/disk/modules/MiqLargeFileWin32.rb
|
283
330
|
- lib/disk/modules/QcowDisk.rb
|
284
331
|
- lib/disk/modules/QcowDiskProbe.rb
|
285
332
|
- lib/disk/modules/RawBlockIO.rb
|
@@ -521,7 +568,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
521
568
|
version: '0'
|
522
569
|
requirements: []
|
523
570
|
rubyforge_project:
|
524
|
-
rubygems_version: 2.6.
|
571
|
+
rubygems_version: 2.6.12
|
525
572
|
signing_key:
|
526
573
|
specification_version: 4
|
527
574
|
summary: ManageIQ SmartState Analysis
|
@@ -1,107 +0,0 @@
|
|
1
|
-
require 'memory_buffer'
|
2
|
-
require 'Win32API'
|
3
|
-
|
4
|
-
class MiqLargeFileWin32
|
5
|
-
# Access specifiers.
|
6
|
-
GENERIC_READ = 0x80000000
|
7
|
-
GENERIC_WRITE = 0x40000000
|
8
|
-
|
9
|
-
# Share specifiers.
|
10
|
-
FILE_SHARE_READ = 0x00000001
|
11
|
-
FILE_SHARE_WRITE = 0x00000002
|
12
|
-
|
13
|
-
# Creation disposition specifiers.
|
14
|
-
OPEN_EXISTING = 3
|
15
|
-
|
16
|
-
# Seek origin.
|
17
|
-
FILE_BEGIN = 0
|
18
|
-
FILE_CURRENT = 1
|
19
|
-
FILE_END = 2
|
20
|
-
|
21
|
-
# Misc.
|
22
|
-
INVALID_HANDLE_VALUE = -1
|
23
|
-
|
24
|
-
# API.
|
25
|
-
@@createFile = Win32API.new('kernel32', 'CreateFileA', 'PLLLLLL', 'L')
|
26
|
-
@@setFilePointerEx = Win32API.new('kernel32', 'SetFilePointerEx', 'LLLPL', 'L')
|
27
|
-
@@readFile = Win32API.new('kernel32', 'ReadFile', 'LPLPL', 'L')
|
28
|
-
@@writeFile = Win32API.new('kernel32', 'WriteFile', 'LPLPL', 'L')
|
29
|
-
@@closeHandle = Win32API.new('kernel32', 'CloseHandle', 'L', 'L')
|
30
|
-
@@getFileSize = Win32API.new('kernel32', 'GetFileSizeEx', 'LP', 'L')
|
31
|
-
@@getLastError = Win32API.new('kernel32', 'GetLastError', nil, 'L')
|
32
|
-
|
33
|
-
# Default constructor.
|
34
|
-
def initialize(file, access = "r")
|
35
|
-
accessOptions = 0
|
36
|
-
accessOptions |= GENERIC_READ if access.include?("r")
|
37
|
-
accessOptions |= GENERIC_WRITE if access.include?("+")
|
38
|
-
@hFile = @@createFile.call(file, accessOptions, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
|
39
|
-
raise "Couldn't open file #{file}" if @hFile == INVALID_HANDLE_VALUE
|
40
|
-
$log.debug("MiqLargeFile<#{object_id}> Opening #{file}, handle 0x#{'%08x' % @hFile}") if $log
|
41
|
-
end
|
42
|
-
|
43
|
-
# Alternative initialization.
|
44
|
-
def self.open(file, access = "r")
|
45
|
-
initialize(file, access)
|
46
|
-
end
|
47
|
-
|
48
|
-
def size
|
49
|
-
siz = MemoryBuffer.create_quad
|
50
|
-
err = @@getFileSize.call(@hFile, siz)
|
51
|
-
siz.unpack('Q')[0]
|
52
|
-
end
|
53
|
-
|
54
|
-
def seek(offset, whence)
|
55
|
-
method = case whence
|
56
|
-
when IO::SEEK_SET then FILE_BEGIN
|
57
|
-
when IO::SEEK_CUR then FILE_CURRENT
|
58
|
-
when IO::SEEK_END then FILE_END
|
59
|
-
else raise "Invalid seek method: #{whence}"
|
60
|
-
end
|
61
|
-
offHi, offLo = offset.divmod(4294967296) # 2 ** 32
|
62
|
-
new_pos = MemoryBuffer.create_quad
|
63
|
-
res = @@setFilePointerEx.call(@hFile, offLo, offHi, new_pos, method)
|
64
|
-
if res == 0
|
65
|
-
last_error = @@getLastError.call
|
66
|
-
raise "SetFilePointerEx failed - Offset:[#{offset}] method:[#{whence}] Handle:[0x#{'%08x' % @hFile}] GetLastErrorNum:[#{last_error}]"
|
67
|
-
end
|
68
|
-
new_pos = new_pos.unpack('Q')[0]
|
69
|
-
new_pos
|
70
|
-
end
|
71
|
-
|
72
|
-
def read(bytes)
|
73
|
-
# puts "#{getFilePos}, #{bytes}" if $track_pos
|
74
|
-
buf = MemoryBuffer.create(bytes)
|
75
|
-
bytesRead = MemoryBuffer.create_long
|
76
|
-
res = @@readFile.call(@hFile, buf, bytes, bytesRead, 0)
|
77
|
-
bytesRead = bytesRead.unpack('L')[0]
|
78
|
-
if bytesRead == 0 && bytes != 0 || res == 0
|
79
|
-
last_error = @@getLastError.call
|
80
|
-
raise "Read from disk file failed - result:[#{res}] bytesRead:[#{bytesRead}] expected:[#{bytes}] file pointer:[#{getFilePos}] file size:[#{size}] Handle:[0x#{'%08x' % @hFile}] GetLastErrorNum:[#{last_error}]."
|
81
|
-
end
|
82
|
-
buf = buf[0...bytesRead] if bytesRead != bytes
|
83
|
-
buf
|
84
|
-
end
|
85
|
-
|
86
|
-
def write(buf, len)
|
87
|
-
# NOTE: len must be a double word.
|
88
|
-
bytesWritten = MemoryBuffer.create_long
|
89
|
-
res = @@writeFile.call(@hFile, buf, len, bytesWritten, 0)
|
90
|
-
raise "WriteFile failed" if res == 0
|
91
|
-
bytesWritten = bytesWritten.unpack('L')[0]
|
92
|
-
raise "Not all data written" if bytesWritten != len
|
93
|
-
bytesWritten
|
94
|
-
end
|
95
|
-
|
96
|
-
def close
|
97
|
-
$log.debug("MiqLargeFile<#{object_id}> Closing handle 0x#{'%08x' % @hFile}") if $log
|
98
|
-
h = @hFile
|
99
|
-
res = @@closeHandle.call(@hFile)
|
100
|
-
@hFile = INVALID_HANDLE_VALUE if res != 0
|
101
|
-
return res, h
|
102
|
-
end
|
103
|
-
|
104
|
-
def getFilePos
|
105
|
-
seek(0, IO::SEEK_CUR)
|
106
|
-
end
|
107
|
-
end
|