wakame-vdc-agents 10.11.0

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.
Files changed (58) hide show
  1. data/LICENSE +202 -0
  2. data/NOTICE +1 -0
  3. data/Rakefile +142 -0
  4. data/bin/hva +972 -0
  5. data/bin/nsa +147 -0
  6. data/bin/sta +182 -0
  7. data/config/hva.conf.example +10 -0
  8. data/config/initializers/isono.rb +43 -0
  9. data/config/initializers/passenger.rb +6 -0
  10. data/config/initializers/sequel.rb +21 -0
  11. data/config/nsa.conf.example +9 -0
  12. data/config/path_resolver.rb +12 -0
  13. data/lib/dcmgr.rb +115 -0
  14. data/lib/dcmgr/endpoints/core_api.rb +1004 -0
  15. data/lib/dcmgr/endpoints/core_api_mock.rb +816 -0
  16. data/lib/dcmgr/endpoints/errors.rb +55 -0
  17. data/lib/dcmgr/endpoints/metadata.rb +129 -0
  18. data/lib/dcmgr/logger.rb +44 -0
  19. data/lib/dcmgr/models/account.rb +104 -0
  20. data/lib/dcmgr/models/account_resource.rb +16 -0
  21. data/lib/dcmgr/models/base.rb +69 -0
  22. data/lib/dcmgr/models/base_new.rb +371 -0
  23. data/lib/dcmgr/models/frontend_system.rb +38 -0
  24. data/lib/dcmgr/models/host_pool.rb +102 -0
  25. data/lib/dcmgr/models/image.rb +46 -0
  26. data/lib/dcmgr/models/instance.rb +255 -0
  27. data/lib/dcmgr/models/instance_netfilter_group.rb +16 -0
  28. data/lib/dcmgr/models/instance_nic.rb +68 -0
  29. data/lib/dcmgr/models/instance_spec.rb +21 -0
  30. data/lib/dcmgr/models/ip_lease.rb +42 -0
  31. data/lib/dcmgr/models/netfilter_group.rb +88 -0
  32. data/lib/dcmgr/models/netfilter_rule.rb +21 -0
  33. data/lib/dcmgr/models/network.rb +32 -0
  34. data/lib/dcmgr/models/physical_host.rb +67 -0
  35. data/lib/dcmgr/models/request_log.rb +25 -0
  36. data/lib/dcmgr/models/ssh_key_pair.rb +55 -0
  37. data/lib/dcmgr/models/storage_pool.rb +134 -0
  38. data/lib/dcmgr/models/tag.rb +126 -0
  39. data/lib/dcmgr/models/tag_mapping.rb +28 -0
  40. data/lib/dcmgr/models/volume.rb +130 -0
  41. data/lib/dcmgr/models/volume_snapshot.rb +47 -0
  42. data/lib/dcmgr/node_modules/hva_collector.rb +134 -0
  43. data/lib/dcmgr/node_modules/sta_collector.rb +72 -0
  44. data/lib/dcmgr/scheduler.rb +12 -0
  45. data/lib/dcmgr/scheduler/find_last.rb +16 -0
  46. data/lib/dcmgr/scheduler/find_random.rb +16 -0
  47. data/lib/dcmgr/stm/instance.rb +25 -0
  48. data/lib/dcmgr/stm/snapshot_context.rb +33 -0
  49. data/lib/dcmgr/stm/volume_context.rb +65 -0
  50. data/lib/dcmgr/web/base.rb +21 -0
  51. data/lib/sinatra/accept_media_types.rb +128 -0
  52. data/lib/sinatra/lazy_auth.rb +56 -0
  53. data/lib/sinatra/rabbit.rb +278 -0
  54. data/lib/sinatra/respond_to.rb +272 -0
  55. data/lib/sinatra/sequel_transaction.rb +27 -0
  56. data/lib/sinatra/static_assets.rb +83 -0
  57. data/lib/sinatra/url_for.rb +44 -0
  58. 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