"""Routines that execute various gluster commands

This exports:


"""

import tempfile
import socket
import time
import random
import json
import sys
import os

from integralstor_gridcell import xml_parse


def main():

    print get_volume_quotas('distvol')


if __name__ == "__main__":
    main()

'''
def list_dir (vol_name, path):
  #mypath = path + ".dir"
  print "volname %s. path %s"%(vol_name, path)
  vol = gfapi.Volume("localhost", vol_name)
  print "test"
  vol.mount()
  print "test"
  fd = vol.opendir(path)
  if not isinstance(fd,gfapi.Dir):
    return False, "opendir error %d" % fd
  files = []
  while True:
    #print "next"
    ent = fd.next()
    if not isinstance(ent,gfapi.Dirent):
      break
    name = ent.d_name[:ent.d_reclen]
    print "name=%s"%(name)
    print "full_name=%s/%s"%(path,name)
    #print ent
    if vol.opendir("%s/%s"%(path,name)):
    #if isinstance(ent, gfapi.Dir):
      print "directory"
      if not name in [".", ".."]:
        files.append(name)
    else:
      print "file"
  return files

def remove_sled(scl, sled):

  ol = []

  localhost = socket.gethostname().strip()
  if "hostname" in scl[sled*2] and scl[sled*2]["in_cluster"] and scl[sled*2]["hostname"] != localhost:
    d = {}
    command = 'gluster peer detach %s --xml'%scl[sled*2]["hostname"]
    d["actual_command"] = command
    node_num = scl[sled*2]["node"]
    if node_num%2:
      node_num = 1
    else:
      node_num = 2
    d["command"] = "Removing sled %d node %d from the storage pool"%(sled+1, node_num)
    #rd = xml_parse.run_command_get_xml_output_tree(command, "/home/bkrram/Documents/software/Django-1.4.3/code/gluster_admin/gluster_admin/utils/test/peer_detach.xml")
    rd = xml_parse.run_command_get_xml_output_tree(command)
    if "error_list" in rd:
      d["error_list"] = rd["error_list"]
    status_dict = None
    if "tree" in rd:
      root = rd["tree"].getroot()
      status_dict = xml_parse.get_op_status(root)
      d["op_status"] = status_dict
    if status_dict and status_dict["op_ret"] == 0:
      #Success so add audit info
      d["audit_str"] = "removed sled %d node %d"%(sled+1, node_num)
    ol.append(d)

    if not status_dict or status_dict["op_ret"] != 0  :
      #Could not get status or something went wrong so bail out
      return ol

  # Previous one succeeded so try next one

  if "hostname" in scl[(sled*2) + 1] and scl[(sled*2) + 1]["in_cluster"] and scl[(sled*2) + 1]["hostname"] != localhost:
    d = {}
    node_num = scl[(sled*2) + 1]["node"]
    if node_num%2:
      node_num = 1
    else:
      node_num = 2
    d["command"] = "Removing sled %d node %d from the storage pool"%(sled+1, node_num)

    command = 'gluster peer detach %s --xml'%scl[(sled*2) + 1]["hostname"]
    d["actual_command"] = command

    #rd = xml_parse.run_command_get_xml_output_tree(command, "/home/bkrram/Documents/software/Django-1.4.3/code/gluster_admin/gluster_admin/utils/test/peer_detach.xml")
    rd = xml_parse.run_command_get_xml_output_tree(command)
    if "error_list" in rd:
      if "error_list" in d:
        d["error_list"].append(rd["error_list"])
      else:
        d["error_list"] = rd["error_list"]

    status_dict = None
    if "tree" in rd:
      root = rd["tree"].getroot()
      status_dict = xml_parse.get_op_status(root)
      d["op_status"] = status_dict
    if status_dict and status_dict["op_ret"] == 0:
      #Success so add audit info
      d["audit_str"] = "removed sled %d node %d"%(sled+1, node_num)
    ol.append(d)

    if (not status_dict or status_dict["op_ret"] != 0)  and scl[sled*2]["hostname"] != localhost:
      #Could not get status or something went wrong so undo the first operation by trying to add node to cluster again
      d = {}
      command = 'gluster peer probe %s --xml'%scl[sled*2]["hostname"]
      d["actual_command"] = command
      node_num = scl[sled*2]["node"]
      if node_num%2:
        node_num = 1
      else:
        node_num = 2
      d["command"] = "Re-adding sled %d node %d to the storage pool as previous node removal failed"%(sled+1, node_num)
      #rd = xml_parse.run_command_get_xml_output_tree(command, "/home/bkrram/Documents/software/Django-1.4.3/code/gluster_admin/gluster_admin/utils/test/peer_probe.xml")
      rd = xml_parse.run_command_get_xml_output_tree(command)
      if "error_list" in rd:
        d["error_list"] = rd["error_list"]
      status_dict = None
      if "tree" in rd:
        root = rd["tree"].getroot()
        status_dict = xml_parse.get_op_status(root)
        d["op_status"] = status_dict
      if status_dict and status_dict["op_ret"] == 0:
        #Succeeded so back out old audit string
        d["audit_str"] = "re-added sled %d node %d to the storage pool as previous node removal failed"%(sled+1, node_num)
      ol.append(d)

  return ol

def build_create_volume_command(vol_name, vol_type, repl_count, transport, scl):

  d = {}
  # Now build the command based on parameters provided
  command = 'gluster volume create %s '%vol_name
  #if vol_type in ['replicated', 'distributed_replicated', 'distributed_striped_replicated', 'striped_replicated']:
  if 'replicate' in vol_type.lower():
    command = command + ' replica %d '%repl_count
  command = command + ' transport %s '%transport

  node_list = []
  if vol_type == "distributed":
    for inode, node in enumerate(scl):
      if node["in_cluster"] == False:
        continue
      node_list.append("Sled %d Node %d "%((inode/2)+1, (inode%2)+1))
      if "hostname" in node:
        brick = "%s:/data/%s"%(node["hostname"], vol_name)
        command = command + brick + " "
  else:
    base = 0
    end = base + (repl_count*2) -1
    while end <= len(scl) :
      num_nodes = 0
      node_in_sled = random.randint(0,1)
      l = []
      incomplete_replica = False
      tmp_command = ""
      while num_nodes < repl_count:
        node_num = base + node_in_sled
        if node_num >= len(scl):
          incomplete_replica = True
          break
        #if scl[node_num]["in_cluster"] == False:
        if scl[node_num]["present"] == False or scl[node_num]["up"]==False or scl[node_num]["in_cluster"] == False:
          base = base + 2
          continue
        if "hostname" in scl[node_num]:
          l.append("Sled %d Node %d "%((node_num/2)+1, node_in_sled+1))
          b = scl[node_num]["hostname"]
          brick = "%s:/data/%s"%(b,vol_name)
          tmp_command = tmp_command + brick + " "
          num_nodes = num_nodes + 1
        base = base + 2
      if not incomplete_replica:
        command = command + tmp_command + " "
        node_list.append(l)
        end = base + (repl_count*2) -1
      else:
        break
  d["cmd"] = command
  d["node_list"] = node_list
  return d
def create_replace_command_file(scl, vil, src_sled, dest_sled):

  data = {}
  data["title"] = "Replacing sled %d with sled %d"%(src_sled, dest_sled)
  data["process"] = "replace_sled"
  data["volume_list"] = []
  data["command_list"] = []

  vol_list = ""
  command_list = []
  src_node_list = []

  src_node_list.append((src_sled - 1)*2 )
  src_node_list.append((src_sled - 1)*2 + 1)

  for n in src_node_list:
    if n%2 == 0:
      dest_node = (int(dest_sled) -1)*2
    else:
      dest_node = (int(dest_sled) -1)*2 + 1


    tvl = volume_info.get_volumes_on_node(scl[n], vil)
    for tv in tvl:
      if (not "hostname" in scl[n]) or (not "hostname" in scl[dest_node]):
        continue
      vd = volume_info.get_volume_info(vil, tv)
      if vd["type"].lower() == "distribute":
        d = {}
        #c = "gluster volume replace-brick %s %s:/data/%s %s:/data/%s"%(tv, scl[n]["hostname"], tv, scl[dest_node]["hostname"], tv)
        c = "gluster volume add-brick %s %s:/data/%s --xml"%(tv, scl[dest_node]["hostname"], tv)
        d["type"] = "add_brick"
        d["desc"] = "Adding volume storage in sled %d for volume %s"%(dest_sled, tv)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)
        d = {}
        c = "gluster --mode=script volume remove-brick %s %s:/data/%s start --xml"%(tv, scl[n]["hostname"], tv)
        d["type"] = "remove_brick_start"
        d["desc"] = "Migrating volume storage from sled %d for volume %s start"%(src_sled, tv)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)
        d = {}
        c = "gluster volume remove-brick %s %s:/data/%s status --xml"%(tv, scl[n]["hostname"], tv)
        d["type"] = "remove_brick_status"
        d["desc"] = "Migrating volume storage from sled %d for volume %s status"%(src_sled, tv)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)
        d = {}
        c = "gluster --mode=script volume remove-brick %s %s:/data/%s commit --xml"%(tv, scl[n]["hostname"], tv)
        d["type"] = "remove_brick_commit"
        d["desc"] = "Migrating volume storage from sled %d for volume %s commit"%(src_sled, tv)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)
      else:
        #Replicated vol so for now do a replace-brick
        d = {}
        c = "gluster volume replace-brick %s %s:/data/%s %s:/data/%s commit force --xml"%(tv, scl[n]["hostname"], tv, scl[dest_node]["hostname"], tv)
        #c = "gluster volume add-brick %s %s:/data/%s"%(tv, scl[dest_node]["hostname"], tv)
        d["type"] = "replace_brick_commit"
        #d["desc"] = "Adding volume storage in sled %d for volume %s"%(dest_sled, tv)
        d["desc"] = "Replacing storage location for volume %s from sled %d to sled %d"%(tv, src_sled, dest_sled)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)
        d = {}
        #c = "gluster volume remove-brick %s %s:/data/%s start --xml"%(tv, scl[n]["hostname"], tv)
        c = "gluster volume heal %s full --xml"%tv
        d["type"] = "volume_heal_full"
        d["desc"] = "Migrating volume data from sled %d for volume %s start"%(src_sled, tv)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)
        d = {}
        #c = "gluster volume remove-brick %s %s:/data/%s status --xml"%(tv, scl[n]["hostname"], tv)
        c = "gluster volume heal %s info --xml"%tv
        d["type"] = "volume_heal_info"
        d["desc"] = "Migrating volume data from sled %d for volume %s info"%(src_sled, tv)
        d["command"] = c
        d["status_code"] = 0
        data["command_list"].append(d)

      if not tv in data["volume_list"]:
        data["volume_list"].append(tv)
  try:
    dir = settings.BATCH_COMMANDS_DIR
  except:
    dir = "."

  if not os.path.exists(dir):
    try:
      os.mkdir(dir)
    except OSError:
      return None

  t = time.localtime()
  data["status"] = "Not yet started"
  data["initiate_time"] = time.strftime("%a %b %d %H:%M:%S %Y", t)
  file_name = "%s_%d"%(time.strftime("bp_replace_sled_%b_%d_%Y_%H_%M_%S", t) , int(time.time()))
  full_file_name = "%s/in_process/%s"%(dir, file_name)
  data["status_url"] = "/show/batch_status_details/%s"%file_name
  d = {}
  try:
    with open(full_file_name, "w+") as f:
      json.dump(data, f, indent=2)
  except Exception, e:
    d["error"] = str(e)
  else:
    d["file_name"] = file_name
  return d


def expand_volume(vol_name, hosts):

  d = {}
  brick_name = None
  for host in hosts:
    if brick_name:
      brick_name = brick_name+ " " + "%s:/data/%s"%(host, vol_name)
    else:
      brick_name = "%s:/data/%s"%(host, vol_name)
  command = 'gluster volume add-brick %s %s --xml'%(vol_name, brick_name)
  d['actual_command'] = command
  #rd = xml_parse.run_command_get_xml_output_tree(command, "/home/bkrram/Documents/software/Django-1.4.3/code/gluster_admin/gluster_admin/utils/test/add_brick.xml")
  rd = xml_parse.run_command_get_xml_output_tree(command)
  if "error_list" in rd:
    d["error_list"] = rd["error_list"]
  status_dict = None
  if "tree" in rd:
    root = rd["tree"].getroot()
    status_dict = xml_parse.get_op_status(root)
    d["op_status"] = status_dict
  return d

def add_nodes_to_pool(anl):

  ol = []
  error_list = []
  localhost = socket.gethostname().strip()

  for node in anl:
    host = node["hostname"]
    rc, d, err = add_a_node_to_pool(host, node["host_info"]["interfaces"]["bond0"]["inet"][0]["address"])
    ol.append(d)
    if rc != 0 and err:
      error_list.append(err)
  return ol, error_list


  #Unwanted code below
      d = {}
      d["command"] = "Adding GRIDCell %s to the pool"%host
      cmd = "gluster peer probe %s --xml"%host
      d["actual_command"] = cmd
      #rd = xml_parse.run_command_get_xml_output_tree(cmd, "/home/bkrram/Documents/software/Django-1.4.3/code/gluster_admin/gluster_admin/utils/test/peer_probe.xml")
      rd = xml_parse.run_command_get_xml_output_tree(cmd)
      if "error_list" in rd:
        d["error_list"] = rd["error_list"]
      if "tree" in rd:
        root = rd["tree"].getroot()
        status_dict = xml_parse.get_op_status(root)
        d["op_status"] = status_dict

      if status_dict and status_dict["op_ret"] == 0:
        #Success so add audit info
        d["audit_str"] = "added GRIDCell %s to the storage pool"%host
'''

# vim: tabstop=8 softtabstop=0 expandtab ai shiftwidth=4 smarttab
