Skip to content
This repository was archived by the owner on May 14, 2018. It is now read-only.

Commit fdea329

Browse files
committed
Add required logic for replication to start working
1 parent a69eec4 commit fdea329

File tree

6 files changed

+135
-12
lines changed

6 files changed

+135
-12
lines changed

app/controllers/api/v1/objects_controller.rb

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,25 @@ class Api::V1::ObjectsController < ApplicationController
33
before_action :has_permissions?
44

55
def create
6-
object = params[:object][:payload].read
7-
object_name = Digest::SHA256.hexdigest object
8-
File.open("#{@volume}/#{object_name}", "w") do |f|
9-
f.write object
10-
end
11-
Brain.request path: "/cluster-api/v1/upload-tokens/#{params[:upload_token]}",
12-
method: :delete,
13-
query: { client_ip: request.remote_ip },
6+
object_contents = params[:object][:payload].read
7+
digest = Cell.digest_contents object_contents
8+
object_name = digest[:sha256sum]
9+
object_path = File.join @volume, object_name
10+
File.open(object_path, "w") { |f| f.write object }
11+
Brain.request path: "/cluster-api/v1/objects",
12+
method: :post,
13+
payload: {
14+
client_ip: request.remote_ip,
15+
upload_token: params[:upload_token],
16+
object: {
17+
uuid: SecureRandom.uuid,
18+
name: params[:object][:payload].original_filename,
19+
size: File.size(object_path),
20+
md5sum: digest[:md5sum],
21+
sha1sum: digest[:sha1sum],
22+
sha256sum: digest[:sha256sum]
23+
}
24+
},
1425
access_token: @jwt
1526
ok
1627
end
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,38 @@
11
class ClusterApi::V1::Objects::DownloadController < ClusterApplicationController
22

3+
before_action :has_permissions?
4+
before_action :object_matches?
5+
before_action :source_allowed?
6+
before_action :target_ip_address_allowed?
7+
38
def show
9+
send_file File.join(@source_cell_volume, @object_sha256sum)
10+
end
11+
12+
private
13+
14+
def has_permissions?
15+
if !Brain.ok?(path: "/cluster-api/v1/sync-tokens/#{params[:sync_token]}") do |json_response|
16+
@object_uuid = json_response[:object][:uuid]
17+
@object_sha256sum = json_response[:object][:sha256sum]
18+
@source_cell_uuid = json_response[:source_cell][:uuid]
19+
@source_cell_volume = json_response[:source_cell][:volume]
20+
@target_cell_ip_address = json_response[:target_cell][:ip_address]
21+
end
22+
forbidden
23+
end
24+
end
25+
26+
def object_matches?
27+
forbidden if @object_uuid != params[:uuid]
28+
end
29+
30+
def source_allowed?
31+
forbidden if @source_cell_uuid != Cell.machine_uuid
32+
end
33+
34+
def target_ip_address_allowed?
35+
forbidden if @target_cell_ip_address != request.remote_ip
436
end
537

638
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class ClusterApi::V1::ObjectsController < ClusterApplicationController
2+
3+
before_action :has_permissions?
4+
before_action :target_allowed?
5+
6+
def create
7+
object_contents, _ = Cell.request cell_ip: @source_cell_ip_address,
8+
path: "/cluster-api/v1/objects/#{@object_uuid}/download",
9+
query: { sync_token: params[:sync_token] }
10+
object_path = File.join @target_cell_volume, @object_sha256sum
11+
File.open(object_path, "w") { |f| f.write object_contents.body }
12+
# FIXME: notify brain
13+
ok
14+
end
15+
16+
private
17+
18+
def has_permissions?
19+
if !Brain.ok?(path: "/cluster-api/v1/sync-tokens/#{params[:sync_token]}") do |json_response|
20+
@object_uuid = json_response[:object][:uuid]
21+
@object_sha256sum = json_response[:object][:sha256sum]
22+
@target_cell_uuid = json_response[:target_cell][:uuid]
23+
@target_cell_volume = json_response[:target_cell][:volume]
24+
@source_cell_ip_address = json_response[:source_cell][:ip_address]
25+
end
26+
forbidden
27+
end
28+
end
29+
30+
def target_allowed?
31+
forbidden if @target_cell_uuid != Cell.machine_uuid
32+
end
33+
34+
end

config/initializers/register_cell.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
cell: {
55
uuid: Cell.machine_uuid,
66
fqdn: Cell.fqdn,
7-
volumes: Cell.storage_volumes
7+
volumes: Cell.storage_volumes,
8+
public_ip_address: ENV["HOST_IP_ADDRESS"]
89
}
910
})

config/routes.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require "sidekiq/web"
2+
13
Rails.application.routes.draw do
24
namespace :api do
35
namespace :v1 do
@@ -10,11 +12,12 @@
1012
end
1113
namespace :cluster_api, path: "cluster-api" do
1214
namespace :v1 do
13-
resources :objects, only: [], param: :uuid do
15+
resources :objects, only: :create, param: :uuid do
1416
member do
1517
resource :download, only: :show, controller: "objects/download"
1618
end
1719
end
1820
end
1921
end
22+
mount Sidekiq::Web => "/sidekiq" unless Rails.env.production?
2023
end

lib/cell.rb

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
class Cell
22

33
require "socket"
4+
require "fileutils"
45
require "securerandom"
56
require "sys/filesystem"
67

8+
def self.digest_content(contents)
9+
{
10+
md5sum: Digest::MD5.hexdigest(contents),
11+
sha1sum: Digest::SHA1.hexdigest(contents),
12+
sha256sum: Digest::SHA256.hexdigest(contents)
13+
}
14+
end
15+
716
def self.machine_uuid
8-
File.read("/etc/brain/machine-uuid").strip
17+
File.read("/etc/cell/machine-uuid").strip
918
rescue Errno::ENOENT
19+
FileUtils.mkdir_p "/etc/cell"
1020
SecureRandom.uuid.tap do |machine_uuid|
11-
File.open("/etc/brain/machine-uuid", "w") { |f| f.write machine_uuid }
21+
File.open("/etc/cell/machine-uuid", "w") { |f| f.write machine_uuid }
1222
end
1323
end
1424

@@ -45,4 +55,36 @@ def self.storage_mountpoints
4555
]
4656
end
4757

58+
def self.request(cell_ip:, path:, method: :get, payload: nil, query: nil)
59+
uri = URI("http://#{cell_ip}:#{ENV["CELL_SERVICE_PORT"]}#{path}")
60+
uri.query = URI.encode_www_form(query) if query
61+
http = Net::HTTP.new uri.host, uri.port
62+
req = case method
63+
when :head
64+
Net::HTTP::Head.new uri.request_uri
65+
when :get
66+
Net::HTTP::Get.new uri.request_uri
67+
when :post
68+
Net::HTTP::Post.new uri.request_uri, { "Content-Type" => "application/json" }
69+
when :put
70+
Net::HTTP::Put.new uri.request_uri, { "Content-Type" => "application/json" }
71+
when :patch
72+
Net::HTTP::Patch.new uri.request_uri, { "Content-Type" => "application/json" }
73+
when :delete
74+
Net::HTTP::Delete.new uri.request_uri
75+
else
76+
raise "unknown method"
77+
end
78+
if !%i(head get delete).include?(method) && payload
79+
req.body = payload.to_json
80+
end
81+
response = http.request req
82+
json_response = JSON.parse response.body, symbolize_names: true rescue nil
83+
if block_given?
84+
yield response, json_response
85+
else
86+
return response, json_response
87+
end
88+
end
89+
4890
end

0 commit comments

Comments
 (0)