/*******************************************************************
 * 
 * Copyright (C) 2013 Kevin Reverchon
 * This file/program is part of gZFS free software
 * See COPYING file for details
 * 
 *******************************************************************/
package gZFS;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jfree.util.Log;

import com.ibm.icu.math.BigDecimal;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class zfs {


	private Logger log = Logger.getLogger(getClass().getPackage().getName()+" "+getClass().getCanonicalName());

	private String userLogin;
	private String userPassword;
	private String sshHost;
	private int sshPort;
	private Session session;
	private Hashtable<String,Session> cacheSession = new Hashtable<String, Session>();
	private JSch jsch = new JSch();
	private String outCmd = null ;
	private StringBuilder outErr ;
	private List<Object> zpoolList = new ArrayList<Object>();
	private List<Object> zfsList = new ArrayList<Object>();
	private List<Object> zfsListSnapshots = new ArrayList<Object>();
	private List<Object> zfsGetAllList = new ArrayList<Object>();
	private List<Object> iscsiListConfigVol = new ArrayList<Object>();
	private Hashtable<String,Object> modelZfsVolAndFS = new Hashtable<String, Object>();
	private Hashtable<String,Object> error = new Hashtable<String, Object>();
	private Hashtable<String,zdisk> hashDisks = new Hashtable<String, zdisk>();
	private Hashtable<String,zraid> hashZRaid = new Hashtable<String, zraid>();

	private zpool zpool;
	private zserver zserver;
	private zvol zvol ;
	private zsnapshots zsnapshots;
	private zreplicas zreplicas;
	private ziscsi ziscsi;
	private zdisk zdisk;
	private zraid zraid;
	private List<Object> sidList;
	private List<Object> ipList;
	private Properties prop = new Properties();
	zfs(){
		this.loadConfig();
		this.setZserver();
		this.setZpool();
		this.setZdisk();
		this.setZvol();
		this.setZsnapshots();
		this.setZreplicas();
		this.setZiscsi();
		this.setZraid();
		log.setLevel((Level) Level.DEBUG);
	}

	public void setZvol(){
		zvol= new zvol();
	}

	public gZFS.zvol getZvol(){
		return zvol;
	}

	public boolean connectServer(String host, int port, String userLogin, String userPasswd){
		try {
			setSession(jsch.getSession(userLogin, host, port));
			session.setPassword(userPasswd);
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			session.setConfig(config);
			session.connect();
			getCacheSession().put(host, session);
			if ( session.isConnected()){
				log.debug("Connected");
				return true;
			}else{
				log.debug("not Connected");
				return false;
			}

		} catch (JSchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	public void disconnectAllServer(){
		String[] keysProp = (String[]) this.getCacheSession().keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			this.setSession(getCacheSession().get(keyProp));
			session.disconnect();
			getCacheSession().remove(keyProp);
		}
	}
	public void disconnectServer(){
		this.setSession(getCacheSession().get(this.getZserver().zProperties.get("serverIP").getValue()));
		session.disconnect();
		getCacheSession().remove(this.getZserver().zProperties.get("serverIP").getValue());
	}


	public Boolean executeCmd(String cmd) {
		this.setOutCmd("");
		try {
			
			this.setSession(getCacheSession().get(this.getZserver().zProperties.get("serverIP").getValue()));
			log.debug("executeCMD : "+this.getZserver().zProperties.get("serverIP").getValue());
			ChannelExec channel = (ChannelExec) session.openChannel("exec");
			//((ChannelExec) channel).setCommand("lqs");
			((ChannelExec) channel).setCommand(cmd);
			InputStream in = channel.getInputStream();
			OutputStream out = channel.getOutputStream();
			((ChannelExec) channel).setErrStream(System.err);
			InputStream err = channel.getErrStream();
			channel.connect();
			log.debug("executeCmd "+cmd);
			if (!cmd.equals("/sbin/show-infodisk-cache")){
				BufferedReader reader = new BufferedReader(new InputStreamReader(err));
				outErr = new StringBuilder();
				String line;
				while ((line = reader.readLine()) != null) {
					outErr.append(line);
				}
			}
			
			byte[] tmp = new byte[4096];

			while (true) {

				int ind = 0;
				while (in.available() > 0) {
					int i = in.read(tmp, 0, 4096);
					if (i < 0)
						break;

					this.setOutCmd(this.getOutCmd()+new String(tmp, 0, i));
				}
				if (channel.isClosed()) {
					break;
				}
				try {
					Thread.sleep(900);
				} catch (Exception ee) {
					log.debug(ee);
				}
			}
			channel.disconnect();

		} catch (JSchException e) {
			// TODO Auto-generated catch block
			log.debug("executeCMD "+e.getMessage());
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			log.debug("executeCmd "+e.getMessage());
			e.printStackTrace();
			return false;
		}
		/*for (int cpt=0;cpt < outCmd.length;cpt++ ) {
			log.debug(outCmd[cpt]);
		}*/
		//log.debug(this.getOutCmd());
		return true;
	}

	public Boolean zfsGetAllVolume(String volName){
		zfsGetAllList.clear();
		//clear this.getZvol properties
		String[] keysProp = (String[]) this.getZvol().zProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			this.getZvol().zProperties.get(keyProp).setMultivalues(null);
			this.getZvol().zProperties.get(keyProp).setValue("");;

		}
		if (  this.executeCmd("/sbin/zfs get all "+volName) ){
			log.debug(this.getOutCmd());
			String[] Tsplit = this.getOutCmd().split("\n");
			for (int cpt=1;cpt<Tsplit.length;cpt++){

				log.debug(Tsplit[cpt].replaceAll(volName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " "));
				String[] TsplitLine = Tsplit[cpt].replaceAll(volName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " ").split(" ");
				log.debug(TsplitLine[0]);
				if ( "creation".equalsIgnoreCase(TsplitLine[0])){
					this.getZvol().zProperties.get("creation").setValue(TsplitLine[1]+" "+TsplitLine[2]+" "+TsplitLine[3]+" "+TsplitLine[4]+" "+TsplitLine[5]);;
				}else{
					//this.getZvol().zProperties.containsKey(TsplitLine[0]);
					if (this.getZvol().zProperties.containsKey(TsplitLine[0])){
						this.getZvol().zProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);
						log.debug("ZFS DEBUG "+this.getZvol().zProperties.get(TsplitLine[0]).getNameProperty()+" "+ this.getZvol().zProperties.get(TsplitLine[0]).getValue());
					}
				}
			}
			this.getZvol().zProperties.get("name").setValue(volName);
			//this.getZvol().zProperties.get("name").setValue(volName);
		}


		return true;
	}
	public void zfsGetInfoByProperty(String volName, String propertyName){
		zfsGetAllList.clear();
		if (  this.executeCmd("/sbin/zfs get "+propertyName+" -H "+volName) ){
			log.debug(this.getOutCmd());
			String[] Tsplit = this.getOutCmd().split("\n");
			for (int cpt=0;cpt<Tsplit.length;cpt++){

				log.debug(Tsplit[cpt].replaceAll(volName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " "));
				String[] TsplitLine = Tsplit[cpt].replaceAll(volName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " ").split(" ");
				log.debug(TsplitLine[0]);
				if ( "creation".equalsIgnoreCase(TsplitLine[0])){
					this.getZvol().zProperties.get("creation").setValue(TsplitLine[1]+" "+TsplitLine[2]+" "+TsplitLine[3]+" "+TsplitLine[4]+" "+TsplitLine[5]);;
				}else{
					//this.getZvol().zProperties.containsKey(TsplitLine[0]);
					if (this.getZvol().zProperties.containsKey(TsplitLine[0])){
						this.getZvol().zProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);
						log.debug("ZFS DEBUG "+this.getZvol().zProperties.get(TsplitLine[0]).getNameProperty()+" "+ this.getZvol().zProperties.get(TsplitLine[0]).getValue());
					}
				}
			}
			this.getZvol().zProperties.get("name").setValue(volName);
			//this.getZvol().zProperties.get("name").setValue(volName);
		}

	}


	public Boolean zpoolGetAll(String zpoolName){
		zfsGetAllList.clear();
		//clear this.getZvol properties
		String[] keysProp = (String[]) this.getZpool().zProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			this.getZpool().zProperties.get(keyProp).setMultivalues(null);
			this.getZpool().zProperties.get(keyProp).setValue("");;

		}
		if (  this.executeCmd("/sbin/zpool get all "+zpoolName) ){
			log.debug(this.getOutCmd());
			String[] Tsplit = this.getOutCmd().split("\n");
			for (int cpt=1;cpt<Tsplit.length;cpt++){

				log.debug(Tsplit[cpt].replaceAll(zpoolName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " "));
				String[] TsplitLine = Tsplit[cpt].replaceAll(zpoolName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " ").split(" ");
				log.debug(TsplitLine[0]);
				if ( "creation".equalsIgnoreCase(TsplitLine[0])){
					this.getZpool().zProperties.get("creation").setValue(TsplitLine[1]+" "+TsplitLine[2]+" "+TsplitLine[3]+" "+TsplitLine[4]+" "+TsplitLine[5]);;
				}else{
					//this.getZpool().zProperties.containsKey(TsplitLine[0]);
					if (this.getZpool().zProperties.containsKey(TsplitLine[0])){
						this.getZpool().zProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);
						log.debug("ZFS DEBUG "+this.getZpool().zProperties.get(TsplitLine[0]).getNameProperty()+" "+ this.getZpool().zProperties.get(TsplitLine[0]).getValue());
					}
				}
			}
			this.getZpool().zProperties.get("name").setValue(zpoolName);
			//this.getZvol().zProperties.get("name").setValue(volName);

			this.getZpoolRealUseableSpace(zpoolName);
			log.debug("zpoolGetAll "+this.getZpool().zProperties.get("realuseablespace").getValue());
			this.getZpoolProvisionedSpace(zpoolName);
			if (  this.executeCmd(this.getZserver().zProperties.get("binzpoolgetstate").getValue()+" -n "+this.getZpool().zProperties.get("name").getValue()) ){
				log.debug(this.getOutCmd());
				String[] TsplitOut = this.getOutCmd().split("\n");
				for (int cpt=1;cpt<TsplitOut.length;cpt++){

					String[] TsplitLineState= TsplitOut[cpt].replaceAll("\n","").split(":");
					log.debug(TsplitLineState[0]);
					//this.getZpool().zProperties.containsKey(TsplitLine[0]);
					if (this.getZpool().zProperties.containsKey(TsplitLineState[0])){
						this.getZpool().zProperties.get(TsplitLineState[0]).setValue(TsplitLineState[1]);
						log.debug("ZFS DEBUG "+this.getZpool().zProperties.get(TsplitLineState[0]).getNameProperty()+" "+ this.getZpool().zProperties.get(TsplitLineState[0]).getValue());
					}
				}
				this.getZpool().zProperties.get("name").setValue(zpoolName);
			}

		}


		return true;
	}


	public List<Object> zpoolList(){
		zpoolList.clear();

		if (  this.executeCmd("/sbin/zpool list -H") ){
			String[] Tsplit = this.getOutCmd().split("\n");
			for (int cpt=0;cpt<Tsplit.length;cpt++){
				log.debug(Tsplit[cpt].split("\\s+")[0] );
				zpoolList.add(Tsplit[cpt].split("\\s+")[0]);
				//zpoolNames[ind] = Tsplit[cpt].split("\\s+")[0];
			}
		}
		return zpoolList;
	}

	public List<Object> zfsListSnapshotsByVolFS(String nameVolFS){
		zfsListSnapshots.clear();

		log.debug("zfs list -H -r -t snapshot -oname,used,referenced "+nameVolFS);
		if (  this.executeCmd("/sbin/zfs list -H -r -t snapshot "+nameVolFS) ){
			if ( this.getOutCmd().length() >0){
				String[] Tsplit = this.getOutCmd().split("\n");
				for (int cpt=0;cpt<Tsplit.length;cpt++){
					log.debug(Tsplit[cpt].split("\\s+")[0] );
					zfsListSnapshots.add(Tsplit[cpt].split("\\s+")[0]);
					//zpoolNames[ind] = Tsplit[cpt].split("\\s+")[0];
				}	
			}

		}
		return zfsListSnapshots;
	}

	public Boolean getIscsiListConfigVol(String nameVolFS){
		sidList = new ArrayList<Object>();
		ipList = new ArrayList<Object>();
		//sidList=null;
		//ipList=null;
		log.debug("get-conf-iscsi-volume nameVolFS");
		//Reset ziscsi object
		this.setZiscsi();
		if (  this.executeCmd("/sbin/get-conf-iscsi-volume "+nameVolFS) ){
			String[] Tsplit = this.getOutCmd().split("\n");
			for (int cpt=0;cpt<Tsplit.length;cpt++){

				String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", " ").split(" ");
				if ( "sid".equalsIgnoreCase(TsplitLine[0])){
					sidList.add(TsplitLine[1]);
				}else{
					if ("sessionIP".equalsIgnoreCase(TsplitLine[0])){
						ipList.add(TsplitLine[1]);
						log.debug("sessionIP "+TsplitLine[1]);
					}else{
						//this.getZvol().zProperties.containsKey(TsplitLine[0]);
						if (this.getZiscsi().zProperties.containsKey(TsplitLine[0])&& TsplitLine.length ==2){
							this.getZiscsi().zProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);
						}
					}
				}
			}
			this.getZiscsi().zProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
			this.getZiscsi().zProperties.get("sid").setMultivalues(sidList);
			this.getZiscsi().zProperties.get("sessionIP").setMultivalues(ipList);
			return true;
		}else{
			return false;
		}
	}


	public void getZpoolProvisionedSpace(String zpoolName){
		log.debug("getZpoolProvisionedSpace "+this.getZpool().zProperties.get("realuseablespace").getValue());
		if (  this.executeCmd("/sbin/get-provisioned-space "+zpoolName) ){
			log.debug(this.getOutCmd());
			String[] Tsplit = this.getOutCmd().split("\n");
			log.debug("getZpoolProvisionedSpace "+this.getZpool().zProperties.get("realuseablespace").getValue().substring((this.getZpool().zProperties.get("realuseablespace").getValue().length())));

			String refUnit = this.getZpool().zProperties.get("realuseablespace").getValue().substring((this.getZpool().zProperties.get("realuseablespace").getValue().length()-1), (this.getZpool().zProperties.get("realuseablespace").getValue().length()));


			float totalProvisioned=0;
			log.debug(String.valueOf(totalProvisioned)+refUnit);
			for (int cpt=0;cpt<Tsplit.length;cpt++){

				log.debug(Tsplit[cpt].replaceAll(zpoolName+"\\s+","").replaceAll("\n", "").replaceAll("\\s+", " "));
				String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", " ").split(" ");
				log.debug(TsplitLine[0]);
				totalProvisioned=totalProvisioned+this.convertInReferenceUnit(TsplitLine[2], refUnit);

			}
			log.debug("getZpoolProvisionedSpace "+String.valueOf(totalProvisioned)+refUnit);
			this.getZpool().zProperties.get("provisionspace").setValue(String.valueOf(BigDecimal.valueOf(totalProvisioned).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())+refUnit);
			//this.getZvol().zProperties.get("name").setValue(volName);
			log.debug(String.valueOf(totalProvisioned)+refUnit);


		}
	}

	public void getZpoolRealUseableSpace(String zpoolName){

		this.zfsGetInfoByProperty(zpoolName, "used");
		this.zfsGetInfoByProperty(zpoolName, "available");
		log.debug("getZpoolRealUseableSpace "+this.getZvol().zProperties.get("used").getValue());
		String refUnit = this.getZvol().zProperties.get("used").getValue().substring(this.getZvol().zProperties.get("used").getValue().length()-1, this.getZvol().zProperties.get("used").getValue().length());
		if (!refUnit.equalsIgnoreCase("T")&&!refUnit.equalsIgnoreCase("G")){
			refUnit = this.getZvol().zProperties.get("available").getValue().substring(this.getZvol().zProperties.get("available").getValue().length()-1, this.getZvol().zProperties.get("available").getValue().length());
		}
		log.debug("getZpoolRealUseableSpace "+refUnit);
		float usedSize = this.convertInReferenceUnit(this.getZvol().zProperties.get("used").getValue(), refUnit);
		float availableSize = this.convertInReferenceUnit(this.getZvol().zProperties.get("available").getValue(), refUnit);
		log.debug("getZpoolRealUseableSpace "+String.valueOf(usedSize+availableSize)+refUnit);
		this.getZpool().zProperties.get("realuseablespace").setValue(String.valueOf(BigDecimal.valueOf(usedSize+availableSize).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue())+refUnit);

	}

	public void getZpoolStatus(){
		error.clear();
		if ( !"".equalsIgnoreCase(getZpool().zProperties.get("name").getValue())){

			log.debug("getZpoolStatus");
			hashDisks.clear();
			hashZRaid.clear();
			this.setZraid();
			if ( this.executeCmd("/sbin/show-infodisk-cache")){
				log.debug("getZpoolStatus");
				this.setZdisk();
				if ( outErr.length() ==0){
					//log.debug(this.getOutCmd());
					String namePool="";
					if (this.getOutCmd().length()>0) {

						String[] Tsplit = this.getOutCmd().split("\n");
						for (int cpt=0;cpt<Tsplit.length;cpt++){
							String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", "").replaceAll("'", "").split(":");
							String propertyDisk=TsplitLine[0].toLowerCase();
							String valuePropertyDisk="";

							if (TsplitLine.length==2){
								valuePropertyDisk=TsplitLine[1];	
							}

							if (Tsplit[cpt].equalsIgnoreCase("#infoDisk#")){
								if (!this.getZdisk().zProperties.get("path").getValue().equalsIgnoreCase("") ){
									hashDisks.put("disk"+cpt, this.getZdisk());
									log.debug(this.getZraid().zProperties.get("poolname").getValue()+"-"+this.getZraid().zProperties.get("raidtype").getValue()+"-"+this.getZraid().zProperties.get("raidid").getValue());
									if (!hashZRaid.containsKey(this.getZraid().zProperties.get("poolname").getValue()+"-"+this.getZraid().zProperties.get("raidtype").getValue()+"-"+this.getZraid().zProperties.get("raidid").getValue())){
										this.getZraid().zProperties.get("name").setValue(this.getZraid().zProperties.get("poolname").getValue()+"-"+this.getZraid().zProperties.get("raidtype").getValue()+"-"+this.getZraid().zProperties.get("raidid").getValue());
										hashZRaid.put(this.getZraid().zProperties.get("poolname").getValue()+"-"+this.getZraid().zProperties.get("raidtype").getValue()+"-"+this.getZraid().zProperties.get("raidid").getValue(), this.getZraid());
										this.setZraid();
									}
								}
								this.setZdisk();
							}else{
								if (TsplitLine.length==2){
									valuePropertyDisk=TsplitLine[1];

									if (this.getZdisk().zProperties.containsKey(propertyDisk)){
										this.getZdisk().zProperties.get(propertyDisk).setValue(valuePropertyDisk);
										//log.debug(propertyDisk+" : "+valuePropertyDisk);
									}

									if (this.getZraid().zProperties.containsKey(propertyDisk)){
										this.getZraid().zProperties.get(propertyDisk).setValue(valuePropertyDisk);

										log.debug(propertyDisk+" : "+valuePropertyDisk);
									}
								}
							}

						}
					}
				}
			}
			log.debug("getZpoolStatus : "+hashDisks.size());
			log.debug("getZpoolStatus : "+hashZRaid.size());
			this.setHashDisks(hashDisks);
			this.setHashZRaid(hashZRaid);	

		}

	}


	public void getInfoDisk(){
		if ( this.executeCmd(this.getZserver().zProperties.get("bingetdiskinfo").getValue() +" "+this.getZdisk().zProperties.get("path").getValue())){
			log.debug("getZpoolStatus");
			if ( outErr.length() ==0){
				log.debug(this.getOutCmd());
				if (this.getOutCmd().length()>0) {
					String dataType="";
					String[] Tsplit = this.getOutCmd().split("\n");


					for (int cpt=0;cpt<Tsplit.length;cpt++){

						String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", "").replaceAll("'", "").split(":");
						String propertyDisk=TsplitLine[0];
						String valuePropertyDisk="";


					}
				}
			}
		}
	}


	public void getZsnapshotConfig(){
		log.debug("getZsnapshotConfig");
		this.setZsnapshots();
		if (  this.executeCmd(this.getZserver().zProperties.get("bingetconfsnapshot").getValue()+" "+this.getZvol().zProperties.get("name").getValue()) ){
			if ( outErr.length() ==0){
				log.debug(this.getOutCmd());
				if (this.getOutCmd().length()>0) {
					String[] Tsplit = this.getOutCmd().split("\n");
					for (int cpt=0;cpt<Tsplit.length;cpt++){
						String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", " ").split("=");
						log.debug(TsplitLine.length);
						log.debug(TsplitLine[0]+" "+TsplitLine[1]);

						this.zsnapshots.zSchedulerProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);
					}	
				}

			}else{
				log.debug(this.getOutCmd());
				this.setZsnapshots();
				this.getZsnapshots().zSchedulerProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
				this.getZsnapshots().zSchedulerProperties.get("type").setValue(this.getZvol().zProperties.get("type").getValue());
			}
		}
		this.getZsnapshots().zSchedulerProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
		this.getZsnapshots().zSchedulerProperties.get("type").setValue(this.getZvol().zProperties.get("type").getValue());
	}
	
	public void getZreplicaConfig(){
		log.debug("getZreplicaConfig");
		this.setZreplicas();
		log.debug(this.getZserver().zProperties.get("bingetconfreplica").getValue()+" "+this.getZvol().zProperties.get("name").getValue());
		if (  this.executeCmd(this.getZserver().zProperties.get("bingetconfreplica").getValue()+" "+this.getZvol().zProperties.get("name").getValue()) ){
			if ( outErr.length() ==0){
				log.debug(this.getOutCmd());
				if (this.getOutCmd().length()>0) {
					String[] Tsplit = this.getOutCmd().split("\n");
					for (int cpt=0;cpt<Tsplit.length;cpt++){
						String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", " ").split("=");
						log.debug(TsplitLine.length);
						if (TsplitLine.length>1){
							log.debug(TsplitLine[0]+" "+TsplitLine[1]);
							this.zreplicas.zSchedulerProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);	
						}
					}	
				}

			}else{
				log.debug(this.getOutCmd());
				this.setZreplicas();
				this.getZreplicas().zSchedulerProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
				//this.getZreplicas().zSchedulerProperties.get("type").setValue(this.getZvol().zProperties.get("type").getValue());
			}
		}
		
		
		//this.getZsnapshots().zSchedulerProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
		//this.getZreplicas().zSchedulerProperties.get("type").setValue(this.getZvol().zProperties.get("type").getValue());
	}

	public void zfsEnableSnapshots(){

		String[] keysProp = (String[]) this.getZsnapshots().zSchedulerProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		error.clear();

		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			if ( !this.getZsnapshots().zSchedulerProperties.get(keyProp).getType().equals("nofreeentry") && this.getZsnapshots().zSchedulerProperties.get(keyProp).getValue().equals("") && !"fileconf".equalsIgnoreCase(keyProp)){
				error.put(keyProp, keyProp+" cannot be empty");
			}else{
				if ( this.getZsnapshots().zSchedulerProperties.get(keyProp).getType().equals("nofreeentry") && this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().isEmpty()){
					error.put(keyProp, keyProp+" cannot be empty");
				}else{
					if (this.getZsnapshots().zSchedulerProperties.get(keyProp).getType().equals("nofreeentry") && this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().contains("*") && this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().size()>1){
						error.put(keyProp, keyProp+ " All is not compatible with others selections");
					}
				}

			}
			log.debug(this.getZsnapshots().zSchedulerProperties.get(keyProp).getType()+" "+this.getZsnapshots().zSchedulerProperties.get(keyProp).getValue()+" "+this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues());
		}

		log.debug("ERROR SIZE : "+error.size());
		if ( error.size() ==0){
			//String contentFileCronSnapshot = this.getZsnapshots().formatCronValue(this.getZsnapshots().zSchedulerProperties.get("frequency").getValue(), this.getZsnapshots().zSchedulerProperties.get("dayofweeksnapshots").getValue());
			for ( int i=0;i<keysProp.length;i++){
				String keyProp = keysProp[i];
				log.debug("zfsEnable "+keyProp);
				if ( this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues() != null){
					if ( this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().size() ==1){
						this.getZsnapshots().zSchedulerProperties.get(keyProp).setValue(this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().get(0).toString());
					}else{
						this.getZsnapshots().zSchedulerProperties.get(keyProp).setValue("");
						for ( int cpt=0;cpt<this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().size();cpt++){
							this.getZsnapshots().zSchedulerProperties.get(keyProp).setValue(this.getZsnapshots().zSchedulerProperties.get(keyProp).getValue()+this.getZsnapshots().zSchedulerProperties.get(keyProp).getMultivalues().get(cpt)+",");
						}
						this.getZsnapshots().zSchedulerProperties.get(keyProp).setValue(this.getZsnapshots().zSchedulerProperties.get(keyProp).getValue().substring(0, this.getZsnapshots().zSchedulerProperties.get(keyProp).getValue().length()-1));
					}
				}
			}
			String cronMin = this.getZsnapshots().zSchedulerProperties.get("minutesofsnapshots").getValue();
			String cronHour = this.getZsnapshots().zSchedulerProperties.get("hoursofsnapshots").getValue();
			String cronMonth = this.getZsnapshots().zSchedulerProperties.get("monthsnapshots").getValue();
			String cronDayofMonth = this.getZsnapshots().zSchedulerProperties.get("dayofmonthsnapshots").getValue();
			String cronDayofWeek = this.getZsnapshots().zSchedulerProperties.get("dayofweeksnapshots").getValue();
			String nameVolFS=this.getZsnapshots().zSchedulerProperties.get("name").getValue();
			String typeZFS=this.getZsnapshots().zSchedulerProperties.get("type").getValue();
			String nbsnapshots=this.getZsnapshots().zSchedulerProperties.get("nbsnapshots").getValue();
			if (  this.executeCmd(this.getZserver().zProperties.get("binzfsenablesnapshots").getValue()+" -m "+"\""+cronMin+"\""+
					" -H "+"\""+cronHour+"\""+
					" -M "+"\""+cronMonth+"\""+
					" -D "+"\""+cronDayofMonth+"\""+
					" -d "+"\""+cronDayofWeek+"\""+
					" -N "+"\""+nameVolFS+"\""+
					" -t "+"\""+typeZFS+"\""+
					" -k "+"\""+nbsnapshots+"\"")){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
					String[] Tsplit = this.getOutCmd().split("\n");
					for (int cpt=0;cpt<Tsplit.length;cpt++){
						/*String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", " ").split("=");
						log.debug(TsplitLine.length);
						log.debug(TsplitLine[0]+" "+TsplitLine[1]);
						this.zsnapshots.zSchedulerProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);*/
					}
				}else{
					log.debug(this.getOutCmd());
					this.setZsnapshots();
					this.getZsnapshots().zSchedulerProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
					this.getZsnapshots().zSchedulerProperties.get("type").setValue(this.getZvol().zProperties.get("type").getValue());
				}
			}
		}
	}


	public void zfsDisableSnapshots(){
		error.clear();
		if (  this.executeCmd(this.getZserver().zProperties.get("binzfsdisablesnapshots").getValue()+" -N "+"\""+this.getZsnapshots().zSchedulerProperties.get("name").getValue()+"\"" )){
			if ( outErr.length() ==0){
				log.debug(this.getOutCmd());
			}else{
				log.debug(this.getOutCmd());
				if (outErr.length()>0){
					error.put("binzfsdisablesnapshots", outErr+"\n" );
				}
			}
		}
	}
	
	public void zfsSnapshots(){
		error.clear();
		if ( this.getZsnapshots().zSchedulerProperties.get("fileconf").getValue().isEmpty()){
			error.put("fileconf ", "Please configure the Snapshots");
		}
		if ( error.size() < 1){
			if (  this.executeCmd(this.getZserver().zProperties.get("binzfssnapshots").getValue()+" "+"\""+this.getZsnapshots().zSchedulerProperties.get("fileconf").getValue()+"\"" )){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
				}else{
					log.debug(this.getOutCmd());
					if (outErr.length()>0){
						error.put("binzfssnapshots", outErr+"\n" );
					}
				}
			}
		}
	}
	

	public void zfsEnableReplicas(){

		String[] keysProp = (String[]) this.getZreplicas().zSchedulerProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		error.clear();

		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			log.debug("zfsEnableReplicas "+keyProp);
			if ( !this.getZreplicas().zSchedulerProperties.get(keyProp).getType().equals("nofreeentry") && !this.getZreplicas().zSchedulerProperties.get(keyProp).getType().equals("noupdateable") && this.getZreplicas().zSchedulerProperties.get(keyProp).getValue().equals("")){
				error.put(keyProp, keyProp+" cannot be empty");
			}else{
				if ( "nofreeentry".equalsIgnoreCase(this.getZreplicas().zSchedulerProperties.get(keyProp).getType()) && (this.getZreplicas().zSchedulerProperties.get(keyProp).getPermitValue() !=null)){
					if ( this.getZreplicas().zSchedulerProperties.get(keyProp).getType().equals("nofreeentry") && this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().isEmpty()){
						error.put(keyProp, keyProp+" cannot be empty");
					}else{
						if (this.getZreplicas().zSchedulerProperties.get(keyProp).getType().equals("nofreeentry") && this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().contains("*") && this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().size()>1){
							error.put(keyProp, keyProp+ " All is not compatible with others selections");
						}
					}
				}
			}
			log.debug(this.getZreplicas().zSchedulerProperties.get(keyProp).getType()+" "+this.getZreplicas().zSchedulerProperties.get(keyProp).getValue()+" "+this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues());
		}
		if ("".equalsIgnoreCase(this.getZreplicas().zSchedulerProperties.get("replicapool").getValue())){
			error.put("replicaPool", "replicapool cannot be empty");
		}

		log.debug("ERROR SIZE : "+error.size());
		if ( error.size() ==0){
			//String contentFileCronSnapshot = this.getZsnapshots().formatCronValue(this.getZsnapshots().zSchedulerProperties.get("frequency").getValue(), this.getZsnapshots().zSchedulerProperties.get("dayofweeksnapshots").getValue());
			for ( int i=0;i<keysProp.length;i++){
				String keyProp = keysProp[i];
				log.debug("zfsEnable Replica"+keyProp);
				if ( this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues() != null){
					if ( this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().size() ==1){
						this.getZreplicas().zSchedulerProperties.get(keyProp).setValue(this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().get(0).toString());
					}else{
						this.getZreplicas().zSchedulerProperties.get(keyProp).setValue("");
						for ( int cpt=0;cpt<this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().size();cpt++){
							this.getZreplicas().zSchedulerProperties.get(keyProp).setValue(this.getZreplicas().zSchedulerProperties.get(keyProp).getValue()+this.getZreplicas().zSchedulerProperties.get(keyProp).getMultivalues().get(cpt)+",");
						}
						this.getZreplicas().zSchedulerProperties.get(keyProp).setValue(this.getZreplicas().zSchedulerProperties.get(keyProp).getValue().substring(0, this.getZreplicas().zSchedulerProperties.get(keyProp).getValue().length()-1));
					}
				}
			}
			String cronMin = this.getZreplicas().zSchedulerProperties.get("minutesofreplicas").getValue();
			String cronHour = this.getZreplicas().zSchedulerProperties.get("hoursofreplicas").getValue();
			String cronMonth = this.getZreplicas().zSchedulerProperties.get("monthreplicas").getValue();
			String cronDayofMonth = this.getZreplicas().zSchedulerProperties.get("dayofmonthreplicas").getValue();
			String cronDayofWeek = this.getZreplicas().zSchedulerProperties.get("dayofweekreplicas").getValue();
			String nameVolFS=this.getZreplicas().zSchedulerProperties.get("name").getValue();
			String nameReplica=this.getZreplicas().zSchedulerProperties.get("replicapool").getValue()+"/"+this.getZvol().zProperties.get("name").getValue().split("/")[1];
			String lastSnapshotsReplicated=this.getZreplicas().zSchedulerProperties.get("lastsnapshotreplicated").getValue();
			String nbReplica=this.getZreplicas().zSchedulerProperties.get("nbreplica").getValue();
			String cmd2exec = this.getZserver().zProperties.get("binzfsenablereplicas").getValue()+" -m "+"\""+cronMin+"\""+
					" -H "+"\""+cronHour+"\""+
					" -M "+"\""+cronMonth+"\""+
					" -D "+"\""+cronDayofMonth+"\""+
					" -d "+"\""+cronDayofWeek+"\""+
					" -o "+"\""+nameVolFS+"\""+
					" -r "+"\""+nameReplica+"\""+
					" -n "+"\""+nbReplica+"\"";
			
			if (!"".equalsIgnoreCase(this.getZreplicas().zSchedulerProperties.get("server").getValue()) && (!this.getZserver().zProperties.get("serverIP").getValue().equalsIgnoreCase(this.getZreplicas().zSchedulerProperties.get("server").getValue())) ){
				cmd2exec = cmd2exec +" -s "+this.getZreplicas().zSchedulerProperties.get("server").getValue();
			}
			log.debug(cmd2exec+" "+this.getZreplicas().zSchedulerProperties.get("server").getValue()+" "+this.getZserver().zProperties.get("serverIP").getValue());
			if (  this.executeCmd(cmd2exec)){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
					String[] Tsplit = this.getOutCmd().split("\n");
					for (int cpt=0;cpt<Tsplit.length;cpt++){
						/*String[] TsplitLine = Tsplit[cpt].replaceAll("\n", "").replaceAll("\\s+", " ").split("=");
						log.debug(TsplitLine.length);
						log.debug(TsplitLine[0]+" "+TsplitLine[1]);
						this.zsnapshots.zSchedulerProperties.get(TsplitLine[0]).setValue(TsplitLine[1]);*/
					}
				}else{
					log.debug(this.getOutCmd());
					this.setZreplicas();
					this.getZreplicas().zSchedulerProperties.get("name").setValue(this.getZvol().zProperties.get("name").getValue());
					//this.getZreplicas().zSchedulerProperties.get("type").setValue(this.getZvol().zProperties.get("type").getValue());
				}
			}
		}
	}
	

	public void zfsDisableReplicas(){
		error.clear();
		if (  this.executeCmd(this.getZserver().zProperties.get("binzfsdisablereplicas").getValue()+" -N "+"\""+this.getZreplicas().zSchedulerProperties.get("name").getValue()+"\"" )){
			if ( outErr.length() ==0){
				log.debug(this.getOutCmd());
			}else{
				log.debug(this.getOutCmd());
				if (outErr.length()>0){
					error.put("binzfsdisablereplicas", outErr+"\n" );
				}
			}
		}
	}
	
	public void zfsReplicas(){
		error.clear();
		if ( this.getZreplicas().zSchedulerProperties.get("fileconf").getValue().isEmpty()){
			error.put("fileconf ", "Please configure the replication");
		}
		if ( error.size() < 1){
			if (  this.executeCmd(this.getZserver().zProperties.get("binzfsreplica").getValue()+" "+"\""+this.getZreplicas().zSchedulerProperties.get("fileconf").getValue()+"\" &" )){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
				}else{
					log.debug(this.getOutCmd());
					if (outErr.length()>0){
						error.put("binzfsreplica", outErr+"\n" );
					}
				}
			}
		}
	}
	
	
	public void zfsCreateVolFS(){
		error.clear();
		if (this.getZpool().zProperties.get("name").getValue().equals("")){
			error.put("pool", "Please select a pool");
		}
		String[] keysProp = (String[]) this.getZvol().zProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		String optionsList="";
		for (int i = 0; i < keysProp.length; i++) {
			String keyProp = keysProp[i];
			log.debug(keyProp);
			if ( ("volume".equalsIgnoreCase(this.getZvol().zProperties.get("type").getValue()) && 
					("volume".equalsIgnoreCase(this.getZvol().zProperties.get(keyProp).getPropertyOf()) || 
							"volandfs".equalsIgnoreCase(this.getZvol().zProperties.get(keyProp).getPropertyOf())))) {
				if (this.getZvol().zProperties.get(keyProp).getValue().equals("")&&!this.getZvol().zProperties.get(keyProp).getType().equals("noupdateable")){
					error.put(keyProp, keyProp+" cannot be empty");
				}
				if ( keyProp.equals("volblocksize")&& "".equals(this.getZvol().zProperties.get(keyProp).getValue())){
					error.put(keyProp, keyProp+" cannot be empty");
				}

				String nameVolFS = this.getZvol().zProperties.get("name").getValue();
				//Available space
				if (keyProp.equals("volsize")&& !"".equals(this.getZvol().zProperties.get(keyProp).getValue())){
					String unit = this.getZvol().zProperties.get("volsize").getValue().substring(this.getZvol().zProperties.get("volsize").getValue().length()-1, this.getZvol().zProperties.get("volsize").getValue().length());

					if ( !unit.equalsIgnoreCase("T") && !unit.equalsIgnoreCase("G") && !unit.equalsIgnoreCase("M")){
						error.put("volsize", "Field size : Unit valid est T,G or M");
					}else{
						Float realUseableSpace = this.convertInReferenceUnit(this.getZpool().zProperties.get("realuseablespace").getValue(), unit);
						Float sizeVolFS = this.convertInReferenceUnit(this.getZvol().zProperties.get("volsize").getValue(), unit);
						this.zfsGetInfoByProperty(this.getZpool().zProperties.get("name").getValue(), "used");
						Float usedSpace = this.convertInReferenceUnit(this.getZvol().zProperties.get("used").getValue(), unit);
						this.getZvol().zProperties.get("name").setValue(nameVolFS);
						Float freeSpace = realUseableSpace - usedSpace;
						if ( sizeVolFS > freeSpace){
							error.put("freespace", "No space available. Free Pool Space : "+String.valueOf(freeSpace)+unit);
						}	
					}
				}
				log.debug("zfsCreateVolFS : "+keyProp+" "+this.getZvol().zProperties.get(keyProp).getType());
				if (!keyProp.equals("name") &&  !this.getZvol().zProperties.get(keyProp).getType().equals("noupdateable")){
					log.debug("zfsCreateVolFS :"+keyProp);
					optionsList = optionsList+keyProp+"="+this.getZvol().zProperties.get(keyProp).getValue()+",";
				}
			}else{
				if (("filesystem".equalsIgnoreCase(this.getZvol().zProperties.get("type").getValue()) && 
						"fs".equalsIgnoreCase(this.getZvol().zProperties.get(keyProp).getPropertyOf())||"volandfs".equalsIgnoreCase(this.getZvol().zProperties.get(keyProp).getPropertyOf()))	){
					if (this.getZvol().zProperties.get(keyProp).getValue().equals("")&&!this.getZvol().zProperties.get(keyProp).getType().equals("noupdateable")&&!"quota".equals(keyProp)&&!"reservation".equals(keyProp) ){
						error.put(keyProp, keyProp+" cannot be empty");
					}
					if (("quota".equals(keyProp)||"reservation".equals(keyProp))&&"".equals(this.getZvol().zProperties.get(keyProp).getValue())){
						this.getZvol().zProperties.get(keyProp).setValue("none");
					}
					if (("quota".equals(keyProp)||"reservation".equals(keyProp))&& !"none".equals(this.getZvol().zProperties.get(keyProp).getValue()) &&!"".equals(this.getZvol().zProperties.get(keyProp).getValue())){
						String nameVolFS = this.getZvol().zProperties.get("name").getValue();
						String unit = this.getZvol().zProperties.get(keyProp).getValue().substring(this.getZvol().zProperties.get(keyProp).getValue().length()-1, this.getZvol().zProperties.get(keyProp).getValue().length());	
						if ( !unit.equalsIgnoreCase("T") && !unit.equalsIgnoreCase("G") && !unit.equalsIgnoreCase("M")){
							error.put(keyProp, "Field "+keyProp+" : Unit valid est T,G or M");
						}else{
							Float realUseableSpace = this.convertInReferenceUnit(this.getZpool().zProperties.get("realuseablespace").getValue(), unit);
							Float valueKeyProp = this.convertInReferenceUnit(this.getZvol().zProperties.get(keyProp).getValue(), unit);
							this.zfsGetInfoByProperty(this.getZpool().zProperties.get("name").getValue(), "used");
							Float usedSpace = this.convertInReferenceUnit(this.getZvol().zProperties.get("used").getValue(), unit);
							this.getZvol().zProperties.get("name").setValue(nameVolFS);
							Float freeSpace = realUseableSpace - usedSpace;
							if ( valueKeyProp > freeSpace){
								error.put(keyProp, "Error value for "+keyProp+" : No space available. Free Pool Space : "+String.valueOf(freeSpace)+unit);
							}	
						}
					}
					log.debug("zfsCreateVolFS : "+keyProp+" "+this.getZvol().zProperties.get(keyProp).getType());
					if (!keyProp.equals("name") &&  !this.getZvol().zProperties.get(keyProp).getType().equals("noupdateable")){
						log.debug("zfsCreateVolFS :"+keyProp);
						optionsList = optionsList+keyProp+"="+this.getZvol().zProperties.get(keyProp).getValue()+",";
					}
				}

			}
		}
		if (error.size()==0){
			log.debug(optionsList);
			if ( optionsList.length()>0){
				optionsList=optionsList.substring(0, optionsList.length()-1);	
			}

			if ( "volume".equals(this.getZvol().zProperties.get("type").getValue())&& this.executeCmd(this.getZserver().zProperties.get("binzfscreatevolume").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue()+
					" -p "+this.getZpool().zProperties.get("name").getValue()+
					" -b "+this.getZvol().zProperties.get("volblocksize").getValue()+
					" -s "+this.getZvol().zProperties.get("volsize").getValue()+
					" -o "+optionsList)){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
				}else{
					log.debug(this.getOutCmd());
					error.put("binzfscreatevolume", "Incoherence : Please connect you to server and launch manualy "+this.getZserver().zProperties.get("binzfscreatevolume").getValue() );
				}
			}else{
				if ("filesystem".equals(this.getZvol().zProperties.get("type").getValue())&& this.executeCmd(this.getZserver().zProperties.get("binzfscreatefilesystem").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue()+
						" -p "+this.getZpool().zProperties.get("name").getValue()+
						" -o "+optionsList)){
					if ( outErr.length() ==0){
						log.debug(this.getOutCmd());
					}else{
						log.debug(this.getOutCmd());
						error.put("binzfscreatefilesystem", "Incoherence : Please connect you to server and launch manualy "+this.getZserver().zProperties.get("binzfscreatefilesystem").getValue() );
					}
				}
			}
		}else{
			log.debug("Error : "+error.size());
		}
	}

	public void zfsUmountFS(){
		error.clear();
		if ("".equals(this.getZvol().zProperties.get("name").getValue())){
			error.put("name", "Please select a ZFS FileSystem");
		}
		if (error.size()==0){
			if (this.executeCmd(this.getZserver().zProperties.get("binzfs").getValue()+" umount "+this.getZvol().zProperties.get("name").getValue())){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
				}else{
					log.debug(this.getOutCmd());
					if (outErr.toString().contains("Error")){
						error.put("binzfs", "Incoherence : Please connect you to server and launch manualy "+this.getZserver().zProperties.get("binzfs").getValue() );
					}
				}
			}else{
				error.put("executeCmd", "Problem with the command : "+this.getZserver().zProperties.get("binzfs").getValue()+" umount "+this.getZvol().zProperties.get("name").getValue());
			}
		}

	}

	public void zfsDestroyVolFS(){
		error.clear();
		if ("".equals(this.getZvol().zProperties.get("name").getValue())){
			error.put("name", "Please select a ZFS FileSystem");
		}
		if ( error.size()==0){
			if ( "filesystem".equals(this.getZvol().zProperties.get("type").getValue())){
				if ( this.executeCmd(this.getZserver().zProperties.get("binzfsdelfilesystem").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue() )) {
					if ( outErr.length() ==0){
						log.debug(this.getOutCmd());
					}else{
						log.debug(this.getOutCmd());
						if (outErr.length()>0){
							error.put("binzfsdelvolume", outErr+"\n" );
						}
					}
				}else{
					error.put("executeCmd", "Problem with the command : "+this.getZserver().zProperties.get("binzfsdelfilesystem").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue());
				}	
			}else{
				if ( "volume".equals(this.getZvol().zProperties.get("type").getValue())){
					if ( this.executeCmd(this.getZserver().zProperties.get("binzfsdelvolume").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue() )) {
						if ( outErr.length() ==0){
							log.debug(this.getOutCmd());
						}else{
							log.debug(this.getOutCmd());
							if (outErr.length()>0){
								error.put("binzfsdelvolume", outErr+"\n" );
							}
						}
					}else{
						error.put("executeCmd", "Problem with the command : "+this.getZserver().zProperties.get("binzfsdelvolume").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue());
					}
				}else{
					if ( "snapshot".equals(this.getZvol().zProperties.get("type").getValue())){
						if ( this.executeCmd(this.getZserver().zProperties.get("binzfsdelvolume").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue() )) {
							if ( outErr.length() ==0){
								log.debug(this.getOutCmd());
							}else{
								log.debug(this.getOutCmd());
								if (outErr.length()>0){
									error.put("binzfsdelvolume", outErr+"\n" );
								}
							}
						}else{
							error.put("executeCmd", "Problem with the command : "+this.getZserver().zProperties.get("binzfsdelvolume").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue());
						}
					}
				}
			}

		}
	}

	public void zfsCreateIscsi(){
		String[] keysProp = (String[]) this.getZiscsi().zProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		error.clear();
		if ("filesystem".equals(this.getZvol().zProperties.get("type").getValue())){
			error.put("type", "You cannot add a iscsi configuration for a zfs filesystem");
		}

		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			if (!this.getZiscsi().zProperties.get(keyProp).getType().contains("noupdateable") && !keyProp.equalsIgnoreCase("allowIP")){
				if ( "".equals(this.getZiscsi().zProperties.get(keyProp).getValue())) {
					error.put(keyProp, this.getZiscsi().zProperties.get(keyProp).getLabelProperty()+" cannot be empty" );
				}
			}
		}
		if (!"".equals(this.getZiscsi().zProperties.get("tid").getValue())){
			error.put("tid", "Iscsi is already configured for this volume" );
		}

		if ( error.size() ==0){
			String cmd = this.getZserver().zProperties.get("binzfsaddiscsi").getValue()+" -d "+this.getZserver().zProperties.get("pathzfsvoldevice").getValue()+this.getZiscsi().zProperties.get("name").getValue()
					+" -T "+this.getZiscsi().zProperties.get("exportType").getValue()+
					" -L 0"+
					" -o "+this.getZiscsi().zProperties.get("iomode").getValue()+
					" -l "+this.getZiscsi().zProperties.get("login").getValue()+
					" -p "+this.getZiscsi().zProperties.get("passwd").getValue()+
					" -t "+this.getZiscsi().zProperties.get("name").getValue();
			if (!this.getZiscsi().zProperties.get("allowIP").getValue().isEmpty()){
				cmd = cmd +" -R "+"\""+this.getZiscsi().zProperties.get("allowIP").getValue()+"\"";
			}
			if (  this.executeCmd(cmd)){
				if ( outErr.length() ==0){
					//log.debug(this.getOutCmd());
				}else{
					if (outErr.toString().contains("Error")){
						error.put("pathzfsvoldevice", "Incoherence : Please connect you to server and launch manualy "+this.getZserver().zProperties.get("binzfsaddiscsi").getValue() );
					}
				}
			}
		}		
	}

	public void zfsDelIscsi(){
		error.clear();
		if (!"".equals(this.getZiscsi().zProperties.get("tid").getValue())){
			if (  this.executeCmd(this.getZserver().zProperties.get("binzfsdeliscsi").getValue()+" -T "+"\""+this.getZiscsi().zProperties.get("tid").getValue()+"\"" )){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
				}else{
					log.debug("zdsdelIscsi Error : " +outErr);
					if ( outErr.toString().contains("in use")){
						error.put("binzfsdeliscsi", outErr.toString() );	
					}else{
						error.put("binzfsdeliscsi", outErr+"\n"+"Incoherence : Please connect you to server and launch manualy "+this.getZserver().zProperties.get("binzfsdeliscsi").getValue() );	
					}
				}
			}	
		}

	}


	public void zfsClone(){
		error.clear();
		if ("".equals(this.getZvol().zProperties.get("name").getValue())){
			error.put("name", "Please, select a volume or filesystem to clone" );
		}

		if ( error.size() ==0){
			String cmd = this.getZserver().zProperties.get("binzfsclone").getValue()+" -n "+this.getZvol().zProperties.get("name").getValue();
			if (  this.executeCmd(cmd)){
				if ( outErr.length() ==0){
					log.debug(this.getOutCmd());
					String[] TsplitOut = this.getOutCmd().split("\n");
					if (TsplitOut.length>0){
						String[] TsplitLine = TsplitOut[0].split("name:");
						if (TsplitLine.length>0){
							this.zfsGetAllVolume(TsplitLine[1]);
							if ("".equalsIgnoreCase(this.getZvol().zProperties.get("name").getValue())){
								error.put("zfsclone", "Clone Creation failed");
							}
						}
					}
				}else{
					if (outErr.length()>0){
						error.put("zfsclone", outErr);
					}
				}
			}
		}
	}


	public float convertInReferenceUnit(String value2Convert, String refUnit){

		float convertedValue=0;
		value2Convert = value2Convert.replace(",", ".");
		log.debug("convertInReferenceUnit "+value2Convert+" "+refUnit);
		if ( refUnit.equalsIgnoreCase("T")){
			if (value2Convert.contains("T")){
				convertedValue=Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)));
			}else{
				if (value2Convert.contains("G")){
					convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)))/1024);
				}else{
					if (value2Convert.contains("M")){
						convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)))/1048576);
					}else{
						if (value2Convert.contains("K")){
							convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)))/1073741824);
						}
					}
				}
			}

		}

		if ( refUnit.equalsIgnoreCase("G")){
			if (value2Convert.contains("G")){
				convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1))));
			}else{
				if (value2Convert.contains("T")){
					convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)))*1024);
				}else{
					if (value2Convert.contains("M")){
						convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)))/1024);
					}else{
						if (value2Convert.contains("K")){
							convertedValue=(Float.valueOf(value2Convert.substring(0, (value2Convert.length()-1)))/1048576);
						}
					}
				}
			}
		}
		log.debug("getZpoolProvisionedSpace "+convertedValue);
		return convertedValue;
	}

	public List<Object> zfsList(){
		zfsList.clear();


		if (  this.executeCmd("/sbin/zfs list -H") ){
			String[] Tsplit = this.getOutCmd().split("\n");
			for (int cpt=0;cpt<Tsplit.length;cpt++){
				log.debug(Tsplit[cpt].split("\\s+")[0] );
				zfsList.add(Tsplit[cpt].split("\\s+")[0]);
				//zpoolNames[ind] = Tsplit[cpt].split("\\s+")[0];
			}
		}
		return zfsList;
	}


	public boolean addServer(){

		if (!"".equalsIgnoreCase(this.getZserver().zProperties.get("serverIP").getValue())) {
			this.getZserver().add(System.getProperty("user.home")+prop.getProperty("serverConfDir")+this.getZserver().zProperties.get("serverIP").getValue()+".properties");

		}else{
			return false;
		}
		return true;
	}

	public boolean removeServer(){
		if (!"".equalsIgnoreCase(this.getZserver().zProperties.get("serverIP").getValue())) {
			this.getZserver().remove(System.getProperty("user.home")+prop.getProperty("serverConfDir")+this.getZserver().zProperties.get("serverIP").getValue()+".properties");
			this.getCacheSession().remove(this.getZserver().zProperties.get("serverIP").getValue());
		}
		return false;
	}

	public List<Object> getListServer(){
		String dirName = System.getProperty("user.home")+prop.getProperty("serverConfDir");
		log.debug(System.getProperty("user.home")+prop.getProperty("serverConfDir"));
		File dir = new File(dirName);
		if ( !dir.exists()){
			dir.mkdir();
			log.debug((System.getProperty("user.home")+prop.getProperty("serverConfDir")));
		}
		log.debug((System.getProperty("user.home")+prop.getProperty("serverConfDir")));
		File f = new File(System.getProperty("user.home")+prop.getProperty("serverConfDir"));
		log.debug((System.getProperty("user.home")+prop.getProperty("serverConfDir")));
		File[] list = f.listFiles();
		List<Object> listServer = new ArrayList<Object>();
		for (int i=0;i<list.length;i++){
			listServer.add(list[i].getName().split(".properties")[0]);
		}
		return listServer;
	}

	public void getServer(String serverName){
		this.getZserver().load(System.getProperty("user.home")+prop.getProperty("serverConfDir")+serverName+".properties");
		String[] keysProp = (String[]) this.getZserver().zProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		error.clear();
		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			if (prop.containsKey(keyProp)){
				this.getZserver().zProperties.get(keyProp).setValue(prop.getProperty(keyProp));	
			}

		}
	}

	public void checkBinEnv(){
		String[] keysProp = (String[]) this.getZserver().zProperties.keySet().toArray(new String[0]);
		Arrays.sort(keysProp);
		error.clear();
		for ( int i=0;i<keysProp.length;i++){
			String keyProp = keysProp[i];
			if ( !keyProp.equalsIgnoreCase("serverIP") && !keyProp.equalsIgnoreCase("userLogin") && !keyProp.equalsIgnoreCase("userPasswd")&&!keyProp.equalsIgnoreCase("pathzfsvoldevice")){
				if (  this.executeCmd(prop.getProperty(keyProp)) && ! outErr.toString().contains("No such file or directory")){
					log.debug(prop.getProperty(keyProp));
					log.debug("checkBinEnv "+outErr.toString().contains("No such file or directory"));
				}else{
					error.put(keyProp, outErr.toString());
				}
			}
		}
	}

	public void loadConfig(){

		try {
			InputStream resource = getClass().getResourceAsStream("config.properties");

			prop.load(resource);
			log.debug(prop);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public String getUserPassword() {
		return userPassword;
	}



	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}



	public String getUserLogin() {
		return userLogin;
	}



	public void setUserLogin(String userLogin) {
		this.userLogin = userLogin;
	}



	public String getSshHost() {
		return sshHost;
	}



	public void setSshHost(String sshHost) {
		this.sshHost = sshHost;
	}



	public int getSshPort() {
		return sshPort;
	}



	public void setSshPort(int sshPort) {
		this.sshPort = sshPort;
	}

	public String getOutCmd() {
		return outCmd;
	}

	public void setOutCmd(String out) {
		this.outCmd=out;
	}

	public Session getSession() {
		return session;
	}

	public void setSession(Session session) {
		this.session = session;
	}

	/**
	 * @return the zSnapshot
	 */
	public zsnapshots getZsnapshots() {
		return zsnapshots;
	}

	/**
	 * @param zSnapshot the zSnapshot to set
	 */
	public void setZsnapshots() {
		this.zsnapshots = new zsnapshots();
	}

	public zreplicas getZreplicas() {
		return zreplicas;
	}

	public void setZreplicas() {
		this.zreplicas = new zreplicas();
	}

	/**
	 * @return the ziscsi
	 */
	public ziscsi getZiscsi() {
		return ziscsi;
	}

	/**
	 * @param ziscsi the ziscsi to set
	 */
	public void setZiscsi() {
		this.ziscsi = new ziscsi();
	}

	/**
	 * @return the zserver
	 */
	public zserver getZserver() {
		return zserver;
	}

	/**
	 * @param zserver the zserver to set
	 */
	public void setZserver() {
		this.zserver = new zserver();
	}

	/**
	 * @return the cacheSession
	 */
	public Hashtable<String,Session> getCacheSession() {
		return cacheSession;
	}

	/**
	 * @param cacheSession the cacheSession to set
	 */
	public void setCacheSession(Hashtable<String,Session> cacheSession) {
		this.cacheSession = cacheSession;
	}

	/**
	 * @return the zpool
	 */
	public zpool getZpool() {
		return zpool;
	}

	/**
	 * @param zpool the zpool to set
	 */
	public void setZpool() {
		this.zpool = new zpool();
	}


	public zdisk getZdisk() {
		return zdisk;
	}

	public void setZdisk() {
		this.zdisk = new zdisk();
	}

	/**
	 * @return the error
	 */
	public Hashtable<String,Object> getError() {
		return error;
	}

	/**
	 * @param error the error to set
	 */
	public void setError(Hashtable<String,Object> error) {
		this.error = error;
	}

	public Hashtable<String, zdisk> getHashDisks() {
		return hashDisks;
	}

	public void setHashDisks(Hashtable<String, zdisk> hashDisks) {
		this.hashDisks = hashDisks;
	}

	public zraid getZraid() {
		return zraid;
	}

	public void setZraid() {
		this.zraid = new zraid();
	}



	public Hashtable<String, zraid> getHashZRaid() {
		return hashZRaid;
	}

	public void setHashZRaid(Hashtable<String, zraid> hashZRaid) {
		this.hashZRaid = hashZRaid;
	}

}