description = [[
Scrapes the hbase master status page.  

information gathered:
 * Hbase Version
 * Hbase Complie date
 * Hbase Root Directory
 * Hadoop Version
 * Hadoop Complie date
 * Average Load
 * Zookeeper Quorum Server
 * Associated Region Servers 
 
For more information about Hbase, see:
 * http://hbase.apache.org/
 * http://wiki.apache.org/hadoop/Hbase
]]

---
-- @usage
-- nmap --script hbase-master-info -p 60010 host
--
-- @output
-- | hbase-master-info: 
-- |   Hbase Version: 0.90.1
-- |   Hbase Compiled: Wed May 11 22:33:44 PDT 2011, bob
-- |   HBase Root Directory: hdfs://master.example.com:8020/hbase
-- |   Hadoop Version: 0.20  f415ef415ef415ef415ef415ef415ef415ef415e
-- |   Hadoop Compiled: Wed May 11 22:33:44 PDT 2011, bob
-- |   Average Load: 0.12
-- |   Zookeeper Quorum: zookeeper.example.com:2181
-- |   Region Servers:
-- |     region1.example.com:60030
-- |_    region2.example.com:60030
---


author = "john.r.bond@gmail.com"
license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified"
categories = {"default", "discovery", "safe"}

require ("shortport")
require ("http")
require ("target")

portrule = shortport.port_or_service ({60010}, "hbase-master", {"tcp"})

action = function( host, port )

        local result = {}
	local region_servers = {}
	local uri = "/master.jsp"
	stdnse.print_debug(1, ("%s:HTTP GET %s:%s%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number, uri))
	local response = http.get( host.targetname or host.ip, port.number, uri )
	stdnse.print_debug(1, ("%s: Status %s"):format(SCRIPT_NAME,response['status-line']))  
	if response['status-line']:match("200%s+OK") and response['body']  then
		local body = response['body']:gsub("%%","%%%%")
		stdnse.print_debug(2, ("%s: Body %s\n"):format(SCRIPT_NAME,body))  
		port.version.name = "hbase-master"
                port.version.product = "Apache Hadoop Hbase"
                if body:match("HBase%s+Version</td><td>([^][<]+)") then
                        local version = body:match("HBase%s+Version</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s:Hbase  Version %s"):format(SCRIPT_NAME,version))  
                        table.insert(result, ("Hbase Version: %s"):format(version))
			port.version.version = version
                end
                if body:match("HBase%s+Compiled</td><td>([^][<]+)") then
                        local compiled = body:match("HBase%s+Compiled</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s: Hbase Compiled %s"):format(SCRIPT_NAME,compiled))  
                        table.insert(result, ("Hbase Compiled: %s"):format(compiled))
                end
                if body:match("Directory</td><td>([^][<]+)") then
                        local compiled = body:match("Directory</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s: HBase RootDirectory %s"):format(SCRIPT_NAME,compiled))  
                        table.insert(result, ("HBase Root Directory: %s"):format(compiled))
                end
                if body:match("Hadoop%s+Version</td><td>([^][<]+)") then
                        local version = body:match("Hadoop%s+Version</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s: Hadoop Version %s"):format(SCRIPT_NAME,version))  
                        table.insert(result, ("Hadoop Version: %s"):format(version))
                end
                if body:match("Hadoop%s+Compiled</td><td>([^][<]+)") then
                        local compiled = body:match("Hadoop%s+Compiled</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s: Hadoop Compiled %s"):format(SCRIPT_NAME,compiled))  
                        table.insert(result, ("Hadoop Compiled: %s"):format(compiled))
                end
                if body:match("average</td><td>([^][<]+)") then
                        local average = body:match("average</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s: Average Load %s"):format(SCRIPT_NAME,average))  
                        table.insert(result, ("Average Load: %s"):format(average))
                end
                if body:match("Quorum</td><td>([^][<]+)") then
                        local quorum = body:match("Quorum</td><td>([^][<]+)"):gsub("%s+", " ")
                        stdnse.print_debug(1, ("%s: Zookeeper Quorum %s"):format(SCRIPT_NAME,quorum))  
                        table.insert(result, ("Zookeeper Quorum: %s"):format(quorum))
			if target.ALLOW_NEW_TARGETS then
                        	if quorum:match("([%w%.]+)") then
                                	local newtarget = quorum:match("([%w%.]+)")
                                	stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
                                        local status,err = target.add(newtarget)
                                 end
			end
                end
		for line in string.gmatch(body, "[^\n]+") do
                        stdnse.print_debug(3, ("%s: Line %s\n"):format(SCRIPT_NAME,line))  
                        if line:match("maxHeap") then
                                local region_server=  line:match("\">([^][<]+)</a>")
				stdnse.print_debug(1, ("%s: Region Server %s"):format(SCRIPT_NAME,region_server))  
				table.insert(region_servers, region_server)
				if target.ALLOW_NEW_TARGETS then
					if region_server:match("([%w%.]+)") then
						local newtarget = region_server:match("([%w%.]+)")
						stdnse.print_debug(1, ("%s: Added target: %s"):format(SCRIPT_NAME, newtarget))
						local status,err = target.add(newtarget)
					end
				end
			end
		end
		nmap.set_port_version(host, port, "hardmatched")
	end
	table.insert(result,"Region Servers:")
	table.insert(result,region_servers)
	return stdnse.format_output(true, result)
end
