Class: Sfp::Agent::Handler

Inherits:
WEBrick::HTTPServlet::AbstractServlet
  • Object
show all
Defined in:
lib/sfpagent/agent.rb

Overview

 A class that handles HTTP request.

Instance Method Summary collapse

Constructor Details

#initialize(server, logger) ⇒ Handler

Returns a new instance of Handler.



716
717
718
# File 'lib/sfpagent/agent.rb', line 716

def initialize(server, logger)
	@logger = logger
end

Instance Method Details

#do_DELETE(request, response) ⇒ Object

Handle HTTP DELETE request

uri:

/model            => delete existing model
/model/cache      => delete all cache models
/model/cache/name => delete cache model of agent "name"
/modules          => delete all modules from module database
/modules/name     => delete module "name" from module database
/agents           => delete all agents from agent database
/agents/name      => delete "name" from agent database
/bsig             => delete existing BSig model


880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
# File 'lib/sfpagent/agent.rb', line 880

def do_DELETE(request, response)
	status = 400
	content_type = body = ''
	if not self.trusted(request)
		status = 403
	else
		path = (request.path[-1,1] == '/' ? ryyequest.path.chop : request.path)

		if path == '/model'
			status, content_type, body = self.set_model

		elsif path == '/model/cache'
			status, content_type, body = self.manage_cache_model({:delete => true, :name => :all})

		elsif path =~ /\/model\/cache\/.+/
			status, content_type, body = self.manage_cache_model({:delete => true, :name => path[13, path.length-13]})

		elsif path == '/modules'
			status, content_type, body = self.manage_modules({:uninstall => true, :name => :all})

		elsif path =~ /\/modules\/.+/
			status, content_type, body = self.manage_modules({:uninstall => true, :name => path[9, path.length-9]})

		elsif path == '/agents'
			status, content_type, body = self.manage_agents({:delete => true, :name => :all})

		elsif path == '/bsig'
			status, content_type, body = self.set_bsig

		end

	end
end

#do_GET(request, response) ⇒ Object

Process HTTP GET request

uri:

/pid          => save daemon's PID to a file (only requested from localhost)
/state        => return the current state
/model        => return the current model
/model/cache  => return the cached model
/sfp          => return the SFP description of a module
/modules      => return a list of available modules
/agents       => return a list of agents database
/log          => return last 100 lines of log file
/bsig         => return BSig model
/bsig/flaws   => return flaws of BSig model


734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
# File 'lib/sfpagent/agent.rb', line 734

def do_GET(request, response)
	status = 400
	content_type = body = ''
	if not trusted(request)
		status = 403
	else
		path = (request.path[-1,1] == '/' ? request.path.chop : request.path)
		if path == '/pid' and (request.peeraddr[2] == 'localhost' or request.peeraddr[3] == '127.0.0.1')
			status, content_type, body = save_pid

		elsif path == '/state'
			status, content_type, body = get_state

		elsif path == '/sfpstate'
			status, content_type, body = get_state({:as_sfp => true})

		elsif path =~ /^\/state\/.+/
			status, content_type, body = get_state({:path => path[7, path.length-7]})

		elsif path =~ /^\/sfpstate\/.+/
			status, content_type, body = get_state({:path => path[10, path.length-10]})

		elsif path == '/model'
			status, content_type, body = get_model

		elsif path =~ /\/model\/cache\/.+/
			status, content_type, body = self.get_cache_model({:name => path[13, path.length-13]})

		elsif path == '/bsig'
			status, content_type, body = get_bsig

		elsif path == '/bsig/flaws'
			status = 200
			content_type = 'application/json'
			body = JSON.generate(Sfp::Agent.bsig_engine.get_flaws)

		elsif path =~ /^\/sfp\/.+/
			status, content_type, body = get_sfp({:module => path[10, path.length-10]})

		elsif path == '/modules'
			mods = {}
			Sfp::Agent.get_modules.each { |name,data| mods[name] = data[:hash] }
			status, content_type, body = [200, 'application/json', JSON.generate(mods)]

		elsif path == '/agents'
			status, content_type, body = [200, 'application/JSON', JSON.generate(Sfp::Agent.get_agents)]

		elsif path == '/log'
			status, content_type, body = [200, 'text/plain', Sfp::Agent.get_log(100)]

		end
	end

	response.status = status
	response['Content-Type'] = content_type
	response.body = body
end

#do_POST(request, response) ⇒ Object

 Handle HTTP POST request

uri: /execute => receive an action’s schema and execute it



797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
# File 'lib/sfpagent/agent.rb', line 797

def do_POST(request, response)
	status = 400
	content_type, body = ''
	if not self.trusted(request)
		status = 403
	else
		path = (request.path[-1,1] == '/' ? ryyequest.path.chop : request.path)
		if path == '/execute'
			status, content_type, body = self.execute({:query => request.query})
		end
	end

	response.status = status
	response['Content-Type'] = content_type
	response.body = body
end

#do_PUT(request, response) ⇒ Object

Handle HTTP PUT request

uri:

/model          => receive a new model and then save it
/model/cache    => receive a "cache" model and then save it
/modules        => save the module if parameter "module" is provided
/agents         => save the agents' list if parameter "agents" is provided
/bsig           => receive BSig model and receive it in cached directory
/bsig/satisfier => receive goal request from other agents and then start
                   a satisfier thread in order to achieve it


825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
# File 'lib/sfpagent/agent.rb', line 825

def do_PUT(request, response)
	status = 400
	content_type = body = ''
	if not self.trusted(request)
		status = 403
	else
		path = (request.path[-1,1] == '/' ? ryyequest.path.chop : request.path)

		if path == '/model' and request.query.has_key?('model')
			status, content_type, body = self.set_model({:model => request.query['model']})

		elsif path =~ /\/model\/cache\/.+/ and request.query.length > 0
			status, content_type, body = self.manage_cache_model({:set => true,
			                                                      :name => path[13, path.length-13],
			                                                      :model => request.query['model']})

		elsif path =~ /\/modules\/.+/ and request.query.length > 0
			status, content_type, body = self.manage_modules({:install => true,
			                                                  :name => path[9, path.length-9],
			                                                  :module => request.query['module']})

		elsif path == '/modules' and request.query.length > 0
			status, content_type, body = self.manage_modules({:install => true,
			                                                  :modules => request.query})

		elsif path == '/agents' and request.query.has_key?('agents')
			status, content_type, body = self.manage_agents({:set => true,
			                                                 :agents => request.query['agents']})

		elsif path == '/bsig' and request.query.has_key?('bsig')
			status, content_type, body = self.set_bsig({:query => request.query})

		elsif path == '/bsig/satisfier'
			status, content_type, body = self.satisfy_bsig_request({:query => request.query, :client => request.remote_ip})

		end
	end

	response.status = status
	response['Content-Type'] = content_type
	response.body = body
end

#execute(p = {}) ⇒ Object



1031
1032
1033
1034
1035
1036
1037
1038
# File 'lib/sfpagent/agent.rb', line 1031

def execute(p={})
	return [400, '', ''] if not (p[:query] and p[:query].has_key?('action'))
	begin
		return [200, '', ''] if Sfp::Agent.execute_action(JSON[p[:query]['action']])
	rescue
	end
	[500, '', '']
end

#get_bsig(p = {}) ⇒ Object



1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
# File 'lib/sfpagent/agent.rb', line 1062

def get_bsig(p={})
	bsig = Sfp::Agent.get_bsig

	# The BSig model is not exist
	return [404, '', ''] if bsig.nil?

	# The BSig model is exist, and then send it in JSON
	return [200, 'application/json', JSON.generate(bsig)] if !!bsig

	[500, '', '']
end

#get_cache_model(p = {}) ⇒ Object



954
955
956
957
958
959
960
961
# File 'lib/sfpagent/agent.rb', line 954

def get_cache_model(p={})
	model = Sfp::Agent.get_cache_model(p[:name])
	if model
		[200, 'application/json', JSON.generate(model)]
	else
		[404, '', '']
	end
end

#get_modelObject



1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
# File 'lib/sfpagent/agent.rb', line 1017

def get_model
	# The model is not exist.
	return [404, '', ''] if not File.exist?(Sfp::Agent::ModelFile)

	begin
		# The model is exist, and then send it in JSON.
		return [200, 'application/json', File.read(Sfp::Agent::ModelFile)]
	rescue
	end

	# There is an error when retrieving the model!
	[500, '', '']
end

#get_sfp(p = {}) ⇒ Object



979
980
981
982
983
984
985
986
987
# File 'lib/sfpagent/agent.rb', line 979

def get_sfp(p={})
	begin
		module_name, _ = p[:module].split('/', 2)
		return [200, 'application/json', Sfp::Agent.get_sfp(module_name)]
	rescue Exception => e
		@logger.error "Sending schemata [Failed]\n#{e}"
	end
	[500, '', '']
end

#get_state(p = {}) ⇒ Object



989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
# File 'lib/sfpagent/agent.rb', line 989

def get_state(p={})
	state = Sfp::Agent.get_state(!!p[:as_sfp])

	# The model is not exist.
	return [404, 'text/plain', 'There is no model!'] if state.nil?

	if !!state
		state = state.at?("$." + p[:path].gsub(/\//, '.')) if !!p[:path]
		return [200, 'application/json', JSON.generate({'state'=>state})]
	end

	# There is an error when retrieving the state of the model!
	[500, '', '']
end

#manage_agents(p = {}) ⇒ Object



914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
# File 'lib/sfpagent/agent.rb', line 914

def manage_agents(p={})
	begin
		if p[:delete]
			if p[:name] == :all
				return [200, '', ''] if Sfp::Agent.delete_agents
			elsif p[:name] != ''
				return [200, '', ''] if Sfp::Agent.set_agents({p[:name] => nil})
			else
				return [400, '', '']
			end
		elsif p[:set]
			return [200, '', ''] if Sfp::Agent.set_agents(JSON[p[:agents]])
		end
	rescue Exception => e
		@logger.error "Saving agents list [Failed]\n#{e}\n#{e.backtrace.join("\n")}"
	end
	[500, '', '']
end

#manage_cache_model(p = {}) ⇒ Object



963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
# File 'lib/sfpagent/agent.rb', line 963

def manage_cache_model(p={})
	if p[:set] and p[:name] and p[:model]
		p[:model] = JSON[p[:model]]
		return [200, '', ''] if Sfp::Agent.set_cache_model(p)
	elsif p[:delete] and p[:name]
		if p[:name] == :all
			return [200, '', ''] if Sfp::Agent.set_cache_model
		else
			return [200, '', ''] if Sfp::Agent.set_cache_model({:name => p[:name]})
		end
	else
		return [400, '', '']
	end
	[500, '', '']
end

#manage_modules(p = {}) ⇒ Object



933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
# File 'lib/sfpagent/agent.rb', line 933

def manage_modules(p={})
	if p[:install]
		if p[:name] and p[:module]
			return [200, '', ''] if Sfp::Agent.install_module(p[:name], p[:module])
		elsif p[:modules]
			return [200, '', ''] if Sfp::Agent.install_modules(p[:modules])
		else
			return [400, '', '']
		end
	elsif p[:uninstall]
		if p[:name] == :all
			return [200, '', ''] if Sfp::Agent.uninstall_all_modules
		elsif p[:name] != ''
			return [200, '', ''] if Sfp::Agent.uninstall_module(p[:name])
		else
			return [400, '', '']
		end
	end
	[500, '', '']
end

#satisfy_bsig_request(p = {}) ⇒ Object



1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
# File 'lib/sfpagent/agent.rb', line 1074

def satisfy_bsig_request(p={})
	return [400, '', ''] if not p[:query]

	return [500, '', ''] if Sfp::Agent.bsig_engine.nil?

	req = p[:query]
	return [200, '', ''] if Sfp::Agent.bsig_engine.receive_goal_from_agent(req['id'].to_i, JSON[req['goal']], req['pi'].to_i, p[:client])

	[500, '', '']
end

#save_pidObject



1040
1041
1042
1043
1044
1045
1046
1047
# File 'lib/sfpagent/agent.rb', line 1040

def save_pid
	begin
		File.open(PIDFile, 'w', 0644) { |f| f.write($$.to_s) }
		return [200, '', $$.to_s]
	rescue Exception
	end
	[500, '', '']
end

#set_bsig(p = {}) ⇒ Object



1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
# File 'lib/sfpagent/agent.rb', line 1049

def set_bsig(p={})
	if p[:query] and p[:query].has_key?('bsig')
		# If setting the BSig model was success, then return '200' status
		return [200, '', ''] if Sfp::Agent.set_bsig(JSON[p[:query]['bsig']])
	else
		# Deleting the existing BSig model by setting with Nil, if it's success then return '200' status.
		return [200, '', ''] if Sfp::Agent.set_bsig(nil)
	end

	# There is an error on setting/deleting the BSig model
	[500, '', '']
end

#set_model(p = {}) ⇒ Object



1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
# File 'lib/sfpagent/agent.rb', line 1004

def set_model(p={})
	if p[:model]
		# If setting the model was success, then return '200' status.
		return [200, '', ''] if Sfp::Agent.set_model(JSON[p[:model]])
	else
		# Removing the existing model by setting an empty model, if it's success then return '200' status.
		return [200, '', ''] if Sfp::Agent.set_model({})
	end

	# There is an error on setting the model!
	[500, '', '']
end

#trusted(request) ⇒ Object



1085
1086
1087
# File 'lib/sfpagent/agent.rb', line 1085

def trusted(request)
	true
end