Class: OpenShift::FrontendHttpServer

Inherits:
Model
  • Object
show all
Includes:
Utils::ShellExec
Defined in:
lib/openshift-origin-node/model/frontend_httpd.rb

Overview

Frontend Http Server

Represents the front-end HTTP server on the system.

Note: This is the Apache VirtualHost implementation; other implementations may vary.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils::ShellExec

run_as, shellCmd, #shellCmd

Constructor Details

#initialize(container_uuid, container_name, namespace) ⇒ FrontendHttpServer

Returns a new instance of FrontendHttpServer.



89
90
91
92
93
94
95
96
97
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 89

def initialize(container_uuid, container_name, namespace)
  Syslog.open('openshift-origin-node', Syslog::LOG_PID, Syslog::LOG_LOCAL0) unless Syslog.opened?

  @config = OpenShift::Config.new
  @container_uuid = container_uuid
  @container_name = container_name
  @namespace = namespace
  @cloud_domain = @config.get("CLOUD_DOMAIN")
end

Instance Attribute Details

#container_nameObject (readonly)

Returns the value of attribute container_name.



86
87
88
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 86

def container_name
  @container_name
end

#container_uuidObject (readonly)

Returns the value of attribute container_uuid.



86
87
88
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 86

def container_uuid
  @container_uuid
end

#namespaceObject (readonly)

Returns the value of attribute namespace.



87
88
89
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 87

def namespace
  @namespace
end

Instance Method Details

#add_alias(name) ⇒ Object

Public: Add an alias to this namespace

Examples

add_alias("foo.example.com")
# => nil

Returns nil on Success or raises on Failure



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 172

def add_alias(name)
  dname = clean_server_name(name)
  path = server_alias_path(dname)

  # Aliases must be globally unique across all gears.
  existing = server_alias_search(dname, true)
  if not existing.empty?
    raise FrontendHttpServerAliasException.new("Already exists", @container_uuid, \
                                               @container_name, @namespace, dname )
  end

  File.open(path, "w") do |f|
    f.write("ServerAlias #{dname}")
    f.flush
  end

  create_routes_alias(dname)

  reload_all
end

#clean_server_name(name) ⇒ Object

Private: Validate the server name

The name is validated against DNS host name requirements from RFC 1123 and RFC 952. Additionally, OpenShift does not allow names/aliases to be an IP address.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 219

def clean_server_name(name)
  dname = name.downcase

  if not dname.index(/[^0-9a-z\-.]/).nil?
    raise FrontendHttpServerNameException.new("Invalid characters", @container_uuid, \
                                               @container_name, @namespace, dname )
  end

  if dname.length > 255
    raise FrontendHttpServerNameException.new("Too long", @container_uuid, \
                                              @container_name, @namespace, dname )
  end

  if dname.length == 0
    raise FrontendHttpServerNameException.new("Name was blank", @container_uuid, \
                                              @container_name, @namespace, dname )
  end

  if dname =~ /^\d+\.\d+\.\d+\.\d+$/
    raise FrontendHttpServerNameException.new("IP addresses are not allowed", @container_uuid, \
                                              @container_name, @namespace, dname )
  end

  return dname
end

#connect(path, uri, options = {}) ⇒ Object

Public: Connect a path element to a back-end URI for this namespace.

Examples

connect('/', 'http://127.0.250.1:8080/')
connect('/phpmyadmin, ''http://127.0.250.2:8080/')
connect('/socket, 'http://127.0.250.3:8080/', {:websocket=>1}

# => nil

Returns nil on Success or raises on Failure

Raises:

  • (NotImplementedError)


146
147
148
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 146

def connect(path, uri, options={})
  raise NotImplementedError
end

#createObject

Public: Initialize an empty configuration for this gear

Examples

create
# => nil
# directory for httpd configuration.

Returns nil on Success or raises on Failure



108
109
110
111
112
113
114
115
116
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 108

def create
  basedir = @config.get("GEAR_BASE_DIR")

  token = "#{@container_uuid}_#{@namespace}_#{@container_name}"
  path = File.join(basedir, ".httpd.d", token)

  FileUtils.rm_rf(path) if File.exist?(path)
  FileUtils.mkdir_p(path)      
end

#create_routes_alias(alias_name) ⇒ Object

Create an alias routing file for the node web proxy server



271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 271

def create_routes_alias(alias_name)
  route_file = default_routes_path
  alias_file = File.join(File.dirname(route_file), "routes_alias-#{alias_name}.json")

  begin
    File.open(route_file, 'r') do |fin|
      File.open(alias_file, 'w') do |fout|
        fout.write(fin.read.gsub("#{@container_name}-#{@namespace}.#{@cloud_domain}", "#{alias_name}"))
      end
    end
  rescue => e
    Syslog.alert("ERROR: Failure trying to create routes alias json file: #{@uuid} Exception: #{e.inspect}")
  end
end

#default_routes_pathObject

Get path to the default routes.json file created for the node web proxy



264
265
266
267
268
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 264

def default_routes_path
  basedir = @config.get("GEAR_BASE_DIR")
  token = "#{@container_uuid}_#{@namespace}_#{@container_name}"
  File.join(basedir, '.httpd.d', token, "routes.json")
end

#destroy(async = true) ⇒ Object

Public: Remove the frontend httpd configuration for a gear.

Examples

destroy
# => nil

Returns nil on Success or raises on Failure



126
127
128
129
130
131
132
133
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 126

def destroy(async=true)
  basedir = @config.get("GEAR_BASE_DIR")

  path = File.join(basedir, ".httpd.d", "#{container_uuid}_*")
  FileUtils.rm_rf(Dir.glob(path))

  reload_all(async)
end

#disconnect(path) ⇒ Object

Public: Disconnect a path element from this namespace

Examples

disconnect('/')
disconnect('/phpmyadmin)

# => nil

Returns nil on Success or raises on Failure

Raises:

  • (NotImplementedError)


160
161
162
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 160

def disconnect(path)
  raise NotImplementedError
end

#reload_all(async = false) ⇒ Object

Reload both Apache and the proxy server and combine output/return



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 287

def reload_all(async=false)
  output = ''
  errout = ''
  retc = 0

  out, err, rc = reload_node_web_proxy
  output << out
  errout << err
  retc = rc if rc != 0

  out, err, rc = reload_httpd(async)
  output << out
  errout << err
  retc = rc if rc != 0

  return output, errout, retc
end

#reload_httpd(async = false) ⇒ Object

Reload the Apache configuration



306
307
308
309
310
311
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 306

def reload_httpd(async=false)
  async_opt="-b" if async
  out, err, rc = shellCmd("/usr/sbin/oo-httpd-singular #{async_opt} graceful")
  Syslog.alert("ERROR: failure from oo-httpd-singular(#{rc}): #{@uuid} stdout: #{out} stderr:#{err}") unless rc == 0
  return out, err, rc
end

#reload_node_web_proxyObject

Reload the configuration of the node web proxy server



314
315
316
317
318
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 314

def reload_node_web_proxy
  out, err, rc = shellCmd("service openshift-node-web-proxy reload")
  Syslog.alert("ERROR: failure from openshift-node-web-proxy(#{rc}): #{@uuid} stdout: #{out} stderr:#{err}") unless rc == 0
  return out, err, rc
end

#remove_alias(name) ⇒ Object

Public: Removes an alias from this namespace

Examples

add_alias("foo.example.com")
# => nil

Returns nil on Success or raises on Failure



201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 201

def remove_alias(name)
  dname = clean_server_name(name)
  routes_file_path = server_routes_alias_path(dname)

  FileUtils.rm_f(routes_file_path) if File.exist?(routes_file_path)

  server_alias_search(dname, false).each do |path|
    FileUtils.rm_f(path)
  end

  reload_all
end

#server_alias_path(name) ⇒ Object

Private: Return path to alias file



246
247
248
249
250
251
252
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 246

def server_alias_path(name)
  dname = clean_server_name(name)

  basedir = @config.get("GEAR_BASE_DIR")
  token = "#{@container_uuid}_#{@namespace}_#{@container_name}"
  path = File.join(basedir, '.httpd.d', token, "server_alias-#{dname}.conf")
end

#server_alias_search(name, all_gears = false) ⇒ Object

Private: Search for matching alias files Previously, case sensitive matches were used checking for a duplicate and there are mixed case aliases in use.



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 324

def server_alias_search(name, all_gears=false)
  dname = clean_server_name(name)
  resp = []

  basedir = @config.get("GEAR_BASE_DIR")
  if all_gears
    token = "*"
  else
    token = "#{@container_uuid}_#{@namespace}_#{@container_name}"
  end
  srch = File.join(basedir, ".httpd.d", token, "server_alias-*.conf")
  Dir.glob(srch).each do |fn|
    cmpname = fn.sub(/^.*\/server_alias-(.*)\.conf$/, '\\1')
    if cmpname.casecmp(dname) == 0
      resp << fn
    end
  end
  resp
end

#server_routes_alias_path(name) ⇒ Object

Private: Return path to routes alias file name used by ws proxy server



255
256
257
258
259
260
261
# File 'lib/openshift-origin-node/model/frontend_httpd.rb', line 255

def server_routes_alias_path(name)
  dname = clean_server_name(name)

  basedir = @config.get("GEAR_BASE_DIR")
  token = "#{@container_uuid}_#{@namespace}_#{@container_name}"
  path = File.join(basedir, '.httpd.d', token, "routes_alias-#{dname}.json")
end