wakame-vdc-agents 10.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +202 -0
- data/NOTICE +1 -0
- data/Rakefile +142 -0
- data/bin/hva +972 -0
- data/bin/nsa +147 -0
- data/bin/sta +182 -0
- data/config/hva.conf.example +10 -0
- data/config/initializers/isono.rb +43 -0
- data/config/initializers/passenger.rb +6 -0
- data/config/initializers/sequel.rb +21 -0
- data/config/nsa.conf.example +9 -0
- data/config/path_resolver.rb +12 -0
- data/lib/dcmgr.rb +115 -0
- data/lib/dcmgr/endpoints/core_api.rb +1004 -0
- data/lib/dcmgr/endpoints/core_api_mock.rb +816 -0
- data/lib/dcmgr/endpoints/errors.rb +55 -0
- data/lib/dcmgr/endpoints/metadata.rb +129 -0
- data/lib/dcmgr/logger.rb +44 -0
- data/lib/dcmgr/models/account.rb +104 -0
- data/lib/dcmgr/models/account_resource.rb +16 -0
- data/lib/dcmgr/models/base.rb +69 -0
- data/lib/dcmgr/models/base_new.rb +371 -0
- data/lib/dcmgr/models/frontend_system.rb +38 -0
- data/lib/dcmgr/models/host_pool.rb +102 -0
- data/lib/dcmgr/models/image.rb +46 -0
- data/lib/dcmgr/models/instance.rb +255 -0
- data/lib/dcmgr/models/instance_netfilter_group.rb +16 -0
- data/lib/dcmgr/models/instance_nic.rb +68 -0
- data/lib/dcmgr/models/instance_spec.rb +21 -0
- data/lib/dcmgr/models/ip_lease.rb +42 -0
- data/lib/dcmgr/models/netfilter_group.rb +88 -0
- data/lib/dcmgr/models/netfilter_rule.rb +21 -0
- data/lib/dcmgr/models/network.rb +32 -0
- data/lib/dcmgr/models/physical_host.rb +67 -0
- data/lib/dcmgr/models/request_log.rb +25 -0
- data/lib/dcmgr/models/ssh_key_pair.rb +55 -0
- data/lib/dcmgr/models/storage_pool.rb +134 -0
- data/lib/dcmgr/models/tag.rb +126 -0
- data/lib/dcmgr/models/tag_mapping.rb +28 -0
- data/lib/dcmgr/models/volume.rb +130 -0
- data/lib/dcmgr/models/volume_snapshot.rb +47 -0
- data/lib/dcmgr/node_modules/hva_collector.rb +134 -0
- data/lib/dcmgr/node_modules/sta_collector.rb +72 -0
- data/lib/dcmgr/scheduler.rb +12 -0
- data/lib/dcmgr/scheduler/find_last.rb +16 -0
- data/lib/dcmgr/scheduler/find_random.rb +16 -0
- data/lib/dcmgr/stm/instance.rb +25 -0
- data/lib/dcmgr/stm/snapshot_context.rb +33 -0
- data/lib/dcmgr/stm/volume_context.rb +65 -0
- data/lib/dcmgr/web/base.rb +21 -0
- data/lib/sinatra/accept_media_types.rb +128 -0
- data/lib/sinatra/lazy_auth.rb +56 -0
- data/lib/sinatra/rabbit.rb +278 -0
- data/lib/sinatra/respond_to.rb +272 -0
- data/lib/sinatra/sequel_transaction.rb +27 -0
- data/lib/sinatra/static_assets.rb +83 -0
- data/lib/sinatra/url_for.rb +44 -0
- metadata +270 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr::Models
|
4
|
+
class Tag < BaseNew
|
5
|
+
taggable('tag')
|
6
|
+
with_timestamps
|
7
|
+
plugin :single_table_inheritance, :type_id, :model_map=>{}
|
8
|
+
plugin :subclasses
|
9
|
+
|
10
|
+
inheritable_schema do
|
11
|
+
Fixnum :account_id, :null=>false
|
12
|
+
index :account_id
|
13
|
+
Fixnum :owner_id
|
14
|
+
String :name, :fixed=>true, :size=>200, :null=>false
|
15
|
+
Fixnum :type_id, :null=>false
|
16
|
+
String :attributes
|
17
|
+
end
|
18
|
+
|
19
|
+
TYPE_NORMAL = 0
|
20
|
+
TYPE_AUTH = 1
|
21
|
+
|
22
|
+
many_to_one :account
|
23
|
+
|
24
|
+
#one_to_many :tag_mappings, :dataset=>proc{ TagMapping.dataset.filter(:tag_id=>self.id) } do
|
25
|
+
one_to_many :mapped_uuids, :class=>TagMapping do |ds|
|
26
|
+
ds.instance_eval {
|
27
|
+
def exists?(canonical_uuid)
|
28
|
+
!self.filter(:uuid=>canonical_uuid).empty?
|
29
|
+
end
|
30
|
+
}
|
31
|
+
ds
|
32
|
+
end
|
33
|
+
|
34
|
+
class UnacceptableTagType < StandardError
|
35
|
+
def initialize(msg, tag, taggable)
|
36
|
+
super(msg)
|
37
|
+
|
38
|
+
raise ArgumentError, "Expected #{Tag.class}: #{tag.class}" unless tag.is_a?(Tag)
|
39
|
+
raise ArgumentError, "Expected #{Taggable.class}: #{tag.class}" unless taggable.is_a?(Taggable)
|
40
|
+
@tag = tag
|
41
|
+
@taggable = taggable
|
42
|
+
end
|
43
|
+
#TODO: show @tag and @taggable info to the error message.
|
44
|
+
end
|
45
|
+
class TagAlreadyLabeled < StandardError; end
|
46
|
+
class TagAlreadyUnlabeled < StandardError; end
|
47
|
+
|
48
|
+
def labeled?(canonical_uuid)
|
49
|
+
# TODO: check if the uuid exists
|
50
|
+
|
51
|
+
!TagMapping.filter(:uuid=>canonical_uuid, :tag_id=>self.pk).empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def label(canonical_uuid)
|
55
|
+
tgt = Taggable.find(canonical_uuid)
|
56
|
+
|
57
|
+
raise(UnacceptableTagType, self, tgt) if accept_mapping?(tgt)
|
58
|
+
raise(TagAlreadyLabeled) if labeled?(canonical_uuid)
|
59
|
+
TagMapping.create(:uuid=>canonical_uuid, :tag_id=>self.pk)
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def unlabel(canonical_uuid)
|
64
|
+
t = TagMapping.find(:uuid=>canonical_uuid, :tag_id=>self.pk) || raise(TagAlreadyUnlabeled)
|
65
|
+
t.delete
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
#many_to_many :tags, :join_table=>:tag_mappings, :left_key=>:target_id, :conditions=>{:target_type=>TagMapping::TYPE_TAG}
|
70
|
+
|
71
|
+
#many_to_one :owner, :class=>:User
|
72
|
+
|
73
|
+
#one_to_many :tag_attributes, :one_to_one=>true
|
74
|
+
|
75
|
+
def self.find_tag_class(name)
|
76
|
+
self.subclasses.find { |m|
|
77
|
+
m.to_s.sub(/^#{self.class}::/, '') == name
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
# STI class variable setter, getter methods.
|
82
|
+
class << self
|
83
|
+
|
84
|
+
# Declare the integer number for the tag.
|
85
|
+
#
|
86
|
+
# Also set the value to sti map in class Tag.
|
87
|
+
# class Tag1 < Tag
|
88
|
+
# type_id 123456
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# puts Tag1.type_id # == 123456
|
92
|
+
def type_id(type_id=nil)
|
93
|
+
if type_id.is_a?(Fixnum)
|
94
|
+
@type_id = type_id
|
95
|
+
Tag.sti_model_map[type_id] = self
|
96
|
+
Tag.sti_key_map[self.to_s] = type_id
|
97
|
+
end
|
98
|
+
@type_id || raise("#{self}.type_id is unset. Please set the unique number for the tag instance.")
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# Set or read description of the Tag class.
|
103
|
+
def description(desc=nil)
|
104
|
+
if desc
|
105
|
+
@description = desc
|
106
|
+
end
|
107
|
+
@description
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Check the object class type before associating to the Tag.
|
113
|
+
# Child class must implement this method.
|
114
|
+
# @param taggable_obj any object kind_of?(Model::Taggable)
|
115
|
+
def accept_mapping?(taggable_obj)
|
116
|
+
raise NotImplementedError
|
117
|
+
end
|
118
|
+
|
119
|
+
def after_initialize
|
120
|
+
super
|
121
|
+
self[:type_id] = self.class.type_id
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr::Models
|
4
|
+
class TagMapping < BaseNew
|
5
|
+
TYPE_ACCOUNT = 0
|
6
|
+
TYPE_TAG = 1
|
7
|
+
TYPE_USER = 2
|
8
|
+
TYPE_INSTANCE = 3
|
9
|
+
TYPE_INSTANCE_IMAGE = 4
|
10
|
+
TYPE_HV_CONTROLLER = 5
|
11
|
+
TYPE_HV_AGENT = 6
|
12
|
+
TYPE_PHYSICAL_HOST = 7
|
13
|
+
TYPE_PHYSICAL_HOST_LOCATION = 8
|
14
|
+
TYPE_IMAGE_STORAGE_HOST = 9
|
15
|
+
TYPE_IMAGE_STORAGE = 10
|
16
|
+
|
17
|
+
inheritable_schema do
|
18
|
+
Fixnum :tag_id, :null=>false
|
19
|
+
index :tag_id
|
20
|
+
String :uuid, :null=>false, :fixed=>true, :size=>20
|
21
|
+
index :uuid
|
22
|
+
end
|
23
|
+
|
24
|
+
many_to_one :tag
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'statemachine'
|
3
|
+
|
4
|
+
module Dcmgr::Models
|
5
|
+
class Volume < AccountResource
|
6
|
+
taggable 'vol'
|
7
|
+
|
8
|
+
STATUS_TYPE_REGISTERING = "registering"
|
9
|
+
STATUS_TYPE_ONLINE = "online"
|
10
|
+
STATUS_TYPE_OFFLINE = "offline"
|
11
|
+
STATUS_TYPE_FAILED = "failed"
|
12
|
+
|
13
|
+
STATE_TYPE_REGISTERING = "registering"
|
14
|
+
STATE_TYPE_CREATING = "creating"
|
15
|
+
STATE_TYPE_AVAILABLE = "available"
|
16
|
+
STATE_TYPE_ATTATING = "attating"
|
17
|
+
STATE_TYPE_ATTACHED = "attached"
|
18
|
+
STATE_TYPE_DETACHING = "detaching"
|
19
|
+
STATE_TYPE_FAILED = "failed"
|
20
|
+
STATE_TYPE_DEREGISTERING = "deregistering"
|
21
|
+
STATE_TYPE_DELETING = "deleting"
|
22
|
+
STATE_TYPE_DELETED = "deleted"
|
23
|
+
|
24
|
+
inheritable_schema do
|
25
|
+
Fixnum :storage_pool_id, :null=>false
|
26
|
+
String :status, :null=>false, :default=>STATUS_TYPE_REGISTERING
|
27
|
+
String :state, :null=>false, :default=>STATE_TYPE_REGISTERING
|
28
|
+
Fixnum :size, :null=>false
|
29
|
+
Fixnum :instance_id
|
30
|
+
String :snapshot_id
|
31
|
+
String :host_device_name
|
32
|
+
String :guest_device_name
|
33
|
+
String :export_path, :null=>false
|
34
|
+
Text :transport_information
|
35
|
+
Time :deleted_at
|
36
|
+
Time :attached_at
|
37
|
+
Time :detached_at
|
38
|
+
index :storage_pool_id
|
39
|
+
index :instance_id
|
40
|
+
index :snapshot_id
|
41
|
+
end
|
42
|
+
with_timestamps
|
43
|
+
|
44
|
+
# serialization plugin must be defined at the bottom of all class
|
45
|
+
# method calls.
|
46
|
+
# Possible column data:
|
47
|
+
# iscsi:
|
48
|
+
# {:iqn=>'iqn.1986-03.com.sun:02:a1024afa-775b-65cf-b5b0-aa17f3476bfc', :lun=>0}
|
49
|
+
plugin :serialization, :yaml, :transport_information
|
50
|
+
|
51
|
+
many_to_one :storage_pool
|
52
|
+
many_to_one :instance
|
53
|
+
|
54
|
+
class DiskError < RuntimeError; end
|
55
|
+
class RequestError < RuntimeError; end
|
56
|
+
|
57
|
+
def before_create
|
58
|
+
# check the volume size
|
59
|
+
sp = self.storage_pool
|
60
|
+
volume_size = Volume.dataset.where(:storage_pool_id=> self.storage_pool_id).get{sum(:size)}
|
61
|
+
total_size = sp.offerring_disk_space - volume_size.to_i
|
62
|
+
if self.size > total_size
|
63
|
+
raise DiskError, "out of disk space"
|
64
|
+
end
|
65
|
+
|
66
|
+
super
|
67
|
+
end
|
68
|
+
|
69
|
+
def before_save
|
70
|
+
self.updated_at = Time.now
|
71
|
+
super
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.get_list(account_id, *args)
|
75
|
+
data = args.first
|
76
|
+
vl = self.dataset.where(:account_id=>account_id)
|
77
|
+
vl = vl.limit(data[:limit], data[:start]) if data[:start] && data[:limit]
|
78
|
+
if data[:target] && data[:sort]
|
79
|
+
vl = case data[:sort]
|
80
|
+
when 'desc'
|
81
|
+
vl.order(data[:target].to_sym.desc)
|
82
|
+
when 'asc'
|
83
|
+
vl.order(data[:target].to_sym.asc)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if data[:target] && data[:filter]
|
87
|
+
filter = case data[:target]
|
88
|
+
when 'uuid'
|
89
|
+
data[:filter].split('vol-').last
|
90
|
+
else
|
91
|
+
data[:filter]
|
92
|
+
end
|
93
|
+
vl = vl.grep(data[:target].to_sym, "%#{filter}%")
|
94
|
+
end
|
95
|
+
vl.all.map{|row|
|
96
|
+
row.to_hash_document
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.delete_volume(account_id, uuid)
|
101
|
+
v = self.dataset.where(:account_id=>account_id).where(:uuid=>uuid.split('-').last).first
|
102
|
+
if v.state.to_sym != :available
|
103
|
+
raise RequestError, "invalid delete request"
|
104
|
+
end
|
105
|
+
v.state = :deregistering
|
106
|
+
v.save_changes
|
107
|
+
v
|
108
|
+
end
|
109
|
+
|
110
|
+
def merge_pool_data
|
111
|
+
v = self.to_hash_document
|
112
|
+
v.merge(:storage_pool=>storage_pool.to_hash_document)
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_hash_document
|
116
|
+
h = self.values.dup
|
117
|
+
h[:id] = h[:uuid] = h[:export_path] = self.canonical_uuid
|
118
|
+
# yaml -> hash translation
|
119
|
+
h[:transport_information]=self.transport_information
|
120
|
+
h
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_snapshot(account_id)
|
124
|
+
vs = VolumeSnapshot.create(:account_id=>account_id,
|
125
|
+
:storage_pool_id=>self.storage_pool_id,
|
126
|
+
:origin_volume_id=>self.canonical_uuid,
|
127
|
+
:size=>self.size)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Dcmgr::Models
|
4
|
+
class VolumeSnapshot < AccountResource
|
5
|
+
taggable 'snap'
|
6
|
+
|
7
|
+
STATE_TYPE_REGISTERING = "registering"
|
8
|
+
STATE_TYPE_CREATING = "creating"
|
9
|
+
STATE_TYPE_AVAILABLE = "available"
|
10
|
+
STATE_TYPE_FAILED = "failed"
|
11
|
+
STATE_TYPE_DELETING = "deleting"
|
12
|
+
STATE_TYPE_DELETED = "deleted"
|
13
|
+
|
14
|
+
inheritable_schema do
|
15
|
+
Fixnum :storage_pool_id, :null=>false
|
16
|
+
String :origin_volume_id, :null=>false
|
17
|
+
Fixnum :size, :null=>false
|
18
|
+
Fixnum :status, :null=>false, :default=>0
|
19
|
+
String :state, :null=>false, :default=>STATE_TYPE_REGISTERING
|
20
|
+
index :storage_pool_id
|
21
|
+
end
|
22
|
+
with_timestamps
|
23
|
+
|
24
|
+
many_to_one :storage_pool
|
25
|
+
|
26
|
+
def to_hash_document
|
27
|
+
h = self.values.dup
|
28
|
+
h[:id] = h[:uuid] = self.canonical_uuid
|
29
|
+
h
|
30
|
+
end
|
31
|
+
|
32
|
+
# create volume inherite from this snapshot for the account.
|
33
|
+
# limitation: inherit volume is created on same storage_pool.
|
34
|
+
def create_volume(account_id)
|
35
|
+
storage_pool.create_volume(account_id, self.size, self.canonical_uuid)
|
36
|
+
end
|
37
|
+
|
38
|
+
def origin_volume
|
39
|
+
Volume[origin_volume_id]
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete_snapshot
|
43
|
+
self.state = STATE_TYPE_DELETING
|
44
|
+
self.save_changes
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'isono'
|
3
|
+
require 'ipaddress'
|
4
|
+
|
5
|
+
module Dcmgr
|
6
|
+
module NodeModules
|
7
|
+
class HvaCollector < Isono::NodeModules::Base
|
8
|
+
include Isono::NodeModules
|
9
|
+
|
10
|
+
initialize_hook do
|
11
|
+
rpc = RpcChannel.new(node)
|
12
|
+
app = Isono::Rack::ObjectMethod.new(myinstance)
|
13
|
+
rpc.register_endpoint('hva-collector', Isono::Rack.build do
|
14
|
+
use Isono::Rack::DataStore
|
15
|
+
run proc { |req, res|
|
16
|
+
Thread.current[Models::BaseNew::LOCK_TABLES_KEY] = {}
|
17
|
+
app.call(req, res)
|
18
|
+
}
|
19
|
+
end)
|
20
|
+
end
|
21
|
+
|
22
|
+
terminate_hook do
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_instance(instance_id)
|
26
|
+
Models::Instance.lock!
|
27
|
+
inst = Models::Instance[instance_id]
|
28
|
+
raise "UnknownInstanceID" if inst.nil?
|
29
|
+
|
30
|
+
ret = inst.to_hash
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_instance(instance_id, data)
|
35
|
+
Models::Instance.lock!
|
36
|
+
inst = Models::Instance[instance_id]
|
37
|
+
inst.set_fields(data, [:state]).save
|
38
|
+
# do not respond model object.
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_netfilter_groups_of_instance(instance_id)
|
43
|
+
Models::Instance.lock!
|
44
|
+
inst = Models::Instance[instance_id]
|
45
|
+
raise "UnknownInstanceID" if inst.nil?
|
46
|
+
|
47
|
+
inst.netfilter_groups.map { |g| g.to_hash }
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_group_instance_ipv4s(instance_id)
|
51
|
+
Models::Instance.lock!
|
52
|
+
inst = Models::Instance[instance_id]
|
53
|
+
raise "UnknownInstanceID" if inst.nil?
|
54
|
+
|
55
|
+
insts = inst.netfilter_group_instances
|
56
|
+
ips = insts.map { |instance|
|
57
|
+
next if instance.nil?
|
58
|
+
instance.ips.map { |ip| ip.ipv4 unless ip.nil? }
|
59
|
+
}
|
60
|
+
|
61
|
+
ips.flatten! if ips.size > 0
|
62
|
+
ips.compact
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_network(network_id)
|
66
|
+
Models::Network.lock!
|
67
|
+
network = Models::Network[network_id]
|
68
|
+
raise "UnknownNetworkID" if network.nil?
|
69
|
+
network.to_hash
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_networks
|
73
|
+
Models::Network.lock!
|
74
|
+
networks = Models::Network.all
|
75
|
+
networks.map { |network|
|
76
|
+
network.to_hash
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_dhcp_conf(network_name)
|
81
|
+
Models::Network.lock!
|
82
|
+
network = Models::Network.find(:name=>network_name)
|
83
|
+
raise "Unknown network name: #{network_name}" if network.nil?
|
84
|
+
prefix = IPAddress::Prefix32.new(network.prefix)
|
85
|
+
h = {
|
86
|
+
:ipv4_gw=>network.ipv4_gw,
|
87
|
+
:netmask => prefix.to_ip,
|
88
|
+
:prefix => network.prefix,
|
89
|
+
:dns_server=> network.dns_server,
|
90
|
+
:domain_name => network.domain_name,
|
91
|
+
:mac2addr => [],
|
92
|
+
:addr2host=> [],
|
93
|
+
}
|
94
|
+
|
95
|
+
network.ip_lease.each { |ip|
|
96
|
+
# ignore IPs unbound to vnic.
|
97
|
+
next if ip.instance_nic.nil? || ip.instance_nic.instance.nil?
|
98
|
+
|
99
|
+
h[:mac2addr] << {
|
100
|
+
:mac_addr => ip.instance_nic.pretty_mac_addr,
|
101
|
+
:ipaddr => ip.ipv4
|
102
|
+
}
|
103
|
+
h[:addr2host] << {
|
104
|
+
:hostname => ip.instance_nic.instance.fqdn_hostname,
|
105
|
+
:ipaddr => ip.ipv4
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
h
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_instances_of_netfilter_group(netfilter_group_id)
|
113
|
+
Models::NetfilterGroup.lock!
|
114
|
+
g = Models::NetfilterGroup[netfilter_group_id]
|
115
|
+
raise "UnknownNetfilterGroupID" if g.nil?
|
116
|
+
inst_maps = g.instances.map { |instance| instance.to_hash unless instance.nil? }
|
117
|
+
inst_maps.compact
|
118
|
+
end
|
119
|
+
|
120
|
+
def get_alive_instances(node_id)
|
121
|
+
Models::HostPool.lock!
|
122
|
+
hp = Models::HostPool.find(:node_id => node_id)
|
123
|
+
raise "UnknownNodeID", node_id if hp.nil?
|
124
|
+
|
125
|
+
inst_on_hp = hp.instances_dataset.lives.all.map { |inst|
|
126
|
+
inst.to_hash
|
127
|
+
}
|
128
|
+
inst_on_hp.uniq! if inst_on_hp.size > 0
|
129
|
+
inst_on_hp
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|