forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
file_depot_ftp.rb
137 lines (114 loc) · 3.73 KB
/
file_depot_ftp.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
require 'net/ftp'
class FileDepotFtp < FileDepot
attr_accessor :ftp
def self.uri_prefix
"ftp"
end
def self.validate_settings(settings)
new(:uri => settings[:uri]).verify_credentials(nil, settings.slice(:username, :password))
end
def upload_file(file)
super
with_connection do
return if file_exists?(destination_file)
upload(file.local_file, destination_file)
rescue => err
msg = "Error '#{err.message.chomp}', writing to FTP: [#{uri}], Username: [#{authentication_userid}]"
_log.error(msg)
raise _("Error '%{message}', writing to FTP: [%{uri}], Username: [%{id}]") % {:message => err.message.chomp,
:uri => uri,
:id => authentication_userid}
else
file.update(
:state => "available",
:log_uri => destination_file
)
file.post_upload_tasks
end
end
def remove_file(file)
@file = file
_log.info("Removing log file [#{destination_file}]...")
with_connection do |ftp|
ftp.delete(destination_file.to_s)
end
_log.info("Removing log file [#{destination_file}]...complete")
end
def verify_credentials(_auth_type = nil, cred_hash = nil)
res = with_connection(cred_hash, &:last_response)
raise _("Depot Settings validation failed") unless res
res
end
def with_connection(cred_hash = nil)
raise _("no block given") unless block_given?
_log.info("Connecting through #{self.class.name}: [#{name}]")
begin
connection = connect(cred_hash)
@ftp = connection
yield connection
ensure
connection.try(:close)
@ftp = nil
end
end
def connect(cred_hash = nil)
host = URI(uri).hostname
begin
_log.info("Connecting to #{self.class.name}: #{name} host: #{host}...")
@ftp = Net::FTP.new(host)
@ftp.passive = true # Use passive mode to avoid firewall issues see http://slacksite.com/other/ftp.html#passive
# @ftp.debug_mode = true if settings[:debug] # TODO: add debug option
creds = cred_hash ? [cred_hash[:username], cred_hash[:password]] : login_credentials
@ftp.login(*creds)
_log.info("Connected to #{self.class.name}: #{name} host: #{host}")
rescue SocketError => err
_log.error("Failed to connect. #{err.message}")
raise
rescue Net::FTPPermError => err
_log.error("Failed to login. #{err.message}")
raise
else
@ftp
end
end
def file_exists?(file_or_directory)
!ftp.nlst(file_or_directory.to_s).empty?
rescue Net::FTPPermError
false
end
def self.display_name(number = 1)
n_('FTP', 'FTPs', number)
end
private
def create_directory_structure(directory_path)
pwd = ftp.pwd
directory_path.to_s.split('/').each do |directory|
unless ftp.nlst.include?(directory)
_log.info("creating #{directory}")
ftp.mkdir(directory)
end
ftp.chdir(directory)
end
ftp.chdir(pwd)
end
def upload(source, destination)
create_directory_structure(destination_path)
_log.info("Uploading file: #{destination} to File Depot: #{name}...")
ftp.putbinaryfile(source, destination.to_s)
_log.info("Uploading file: #{destination_file}... Complete")
end
def destination_file
destination_path.join(file.destination_file_name).to_s
end
def destination_path
base_path.join(file.destination_directory)
end
def base_path
# uri: "ftp://ftp.example.com/incoming" => #<Pathname:incoming>
path = URI(URI::DEFAULT_PARSER.escape(uri)).path
Pathname.new(path)
end
def login_credentials
[authentication_userid, authentication_password]
end
end