package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/tls"
	"crypto/x509"
	"database/sql"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	_ "github.com/go-sql-driver/mysql"
	"github.com/labstack/echo"
	"io/ioutil"
	mrand "math/rand"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

type ovirt struct {
}

var MySQLUSER = "apigw"
var MySQLPASS = "^_P+^7Q$bmPj+$xB"

func login(BA string) OvirtObject {
	url := OvirtURL + "/ovirt-engine/api"
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	object := OvirtObject{}
	err = json.Unmarshal(body, &object)
	return object
}

type OvirtObject struct {
	ProductInfo struct {
		Name    string `json:"name"`
		Version struct {
			Build       string `json:"build"`
			FullVersion string `json:"full_version"`
			Major       string `json:"major"`
			Minor       string `json:"minor"`
			Revision    string `json:"revision"`
		} `json:"version"`
	} `json:"product_info"`
	SpecialObjects struct {
		BlankTemplate struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"blank_template"`
		RootTag struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"root_tag"`
	} `json:"special_objects"`
	Time              int64 `json:"time"`
	AuthenticatedUser struct {
		Href string `json:"href"`
		ID   string `json:"id"`
	} `json:"authenticated_user"`
	EffectiveUser struct {
		Href string `json:"href"`
		ID   string `json:"id"`
	} `json:"effective_user"`
	Link []struct {
		Href string `json:"href"`
		Rel  string `json:"rel"`
	} `json:"link"`
}
type TaskHeader struct {
	Name  string `json:"Name,omitempty"`
	Value string `json:"Value,omitempty"`
}
type addVMTask struct {
	URL     string `json:"url"`
	JSON    string `json:__json`
	Method  string `json:"method"`
	Headers []struct {
		Name  string `json:"Name,omitempty"`
		Value string `json:"Value,omitempty"`
	} `json:"headers"`
}
type AddVMRequest struct {
	URL  string `json:"url"`
	JSON struct {
		Name        string `json:"name"`
		Description string `json:"description"`
		Comment     string `json:"comment"`
		Cluster     struct {
			Name string `json:"name"`
		} `json:"cluster"`
		Template struct {
			Name string `json:"name"`
		} `json:"template"`
		CPU struct {
			Topology struct {
				Sockets string `json:"sockets"`
				Cores   string `json:"cores"`
				Threads string `json:"threads"`
			} `json:"topology"`
		} `json:"cpu"`
		Memory       string `json:"memory"`
		MemoryPolicy struct {
			Ballooning string `json:"ballooning"`
			Guaranteed string `json:"guaranteed"`
			OverCommit struct {
				Percent string `json:"percent"`
			} `json:"over_commit"`
		} `json:"memory_policy"`
	} `json:"JSON"`
	Method  string `json:"method"`
	Headers []struct {
		Name  string `json:"Name"`
		Value string `json:"Value"`
	} `json:"headers"`
}
type VMStatistics struct {
	Statistic []struct {
		Kind   string `json:"kind"`
		Type   string `json:"type"`
		Unit   string `json:"unit"`
		Values struct {
			Value []struct {
				Datum float64 `json:"datum"`
			} `json:"value"`
		} `json:"values"`
		VM struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"vm,omitempty"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Href        string `json:"href,omitempty"`
		ID          string `json:"id"`
	} `json:"statistic"`
}

func (o ovirt) vmStatus(uuid string) string {
	type vmStatus struct {
		NextRunConfigurationExists string `json:"next_run_configuration_exists"`
		NumaTuneMode               string `json:"numa_tune_mode"`
		Status                     string `json:"status"`
		StopTime                   int64  `json:"stop_time"`
		OriginalTemplate           struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"original_template"`
		Template struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"template"`
		Actions struct {
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
		} `json:"actions"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Comment     string `json:"comment"`
		Href        string `json:"href"`
		ID          string `json:"id"`
		Bios        struct {
			BootMenu struct {
				Enabled string `json:"enabled"`
			} `json:"boot_menu"`
			Type string `json:"type"`
		} `json:"bios"`
		CPU struct {
			Architecture string `json:"architecture"`
			Topology     struct {
				Cores   string `json:"cores"`
				Sockets string `json:"sockets"`
				Threads string `json:"threads"`
			} `json:"topology"`
		} `json:"cpu"`
		Display struct {
			AllowOverride       string `json:"allow_override"`
			CopyPasteEnabled    string `json:"copy_paste_enabled"`
			DisconnectAction    string `json:"disconnect_action"`
			FileTransferEnabled string `json:"file_transfer_enabled"`
			Monitors            string `json:"monitors"`
			SingleQxlPci        string `json:"single_qxl_pci"`
			SmartcardEnabled    string `json:"smartcard_enabled"`
			Type                string `json:"type"`
		} `json:"display"`
		Initialization struct {
			AuthorizedSSHKeys        string `json:"authorized_ssh_keys"`
			CloudInitNetworkProtocol string `json:"cloud_init_network_protocol"`
			CustomScript             string `json:"custom_script"`
			HostName                 string `json:"host_name"`
			NicConfigurations        struct {
			} `json:"nic_configurations"`
			RegenerateSSHKeys string `json:"regenerate_ssh_keys"`
			UserName          string `json:"user_name"`
		} `json:"initialization"`
		Io struct {
			Threads string `json:"threads"`
		} `json:"io"`
		Memory    string `json:"memory"`
		Migration struct {
			AutoConverge string `json:"auto_converge"`
			Compressed   string `json:"compressed"`
			Encrypted    string `json:"encrypted"`
		} `json:"migration"`
		Origin string `json:"origin"`
		Os     struct {
			Boot struct {
				Devices struct {
					Device []string `json:"device"`
				} `json:"devices"`
			} `json:"boot"`
			Type string `json:"type"`
		} `json:"os"`
		Sso struct {
			Methods struct {
				Method []struct {
					ID string `json:"id"`
				} `json:"method"`
			} `json:"methods"`
		} `json:"sso"`
		Stateless string `json:"stateless"`
		Type      string `json:"type"`
		Usb       struct {
			Enabled string `json:"enabled"`
		} `json:"usb"`
		Cluster struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"cluster"`
		Quota struct {
			ID string `json:"id"`
		} `json:"quota"`
		Link []struct {
			Href string `json:"href"`
			Rel  string `json:"rel"`
		} `json:"link"`
		CPUShares        string `json:"cpu_shares"`
		CreationTime     int64  `json:"creation_time"`
		DeleteProtected  string `json:"delete_protected"`
		HighAvailability struct {
			Enabled  string `json:"enabled"`
			Priority string `json:"priority"`
		} `json:"high_availability"`
		LargeIcon struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"large_icon"`
		MemoryPolicy struct {
			Ballooning string `json:"ballooning"`
			Guaranteed string `json:"guaranteed"`
			Max        string `json:"max"`
		} `json:"memory_policy"`
		MigrationDowntime  string `json:"migration_downtime"`
		MultiQueuesEnabled string `json:"multi_queues_enabled"`
		PlacementPolicy    struct {
			Affinity string `json:"affinity"`
			Hosts    struct {
				Host []struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"host"`
			} `json:"hosts"`
		} `json:"placement_policy"`
		SmallIcon struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"small_icon"`
		StartPaused                 string `json:"start_paused"`
		StorageErrorResumeBehaviour string `json:"storage_error_resume_behaviour"`
		TimeZone                    struct {
			Name string `json:"name"`
		} `json:"time_zone"`
		CPUProfile struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"cpu_profile"`
	}
	//url := "https://ovirt-cl.zi-tel.com/ovirt-engine/api/vms/c1a44128-6c6c-406b-99d8-4a68a99380c9"
	url := OvirtURL + "/ovirt-engine/api/vms/" + uuid
	//fmt.Println("VMSTATUS UUID:" ,uuid)
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println("Error in vmStatus ", err)
		//return "Null"
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	//fmt.Println("in vmStatus 1 " )
	//TODO: replace BA
	req.Header.Add("Authorization", "Basic YWRtaW5AaW50ZXJuYWw6a2VsYW5zaCBqMw==")
	//fmt.Println("in vmStatus 1 2 " )

	res, err := client.Do(req)
	//fmt.Println("in vmStatus :",err )
	if err != nil {
		fmt.Println("Error in vmStatus ", err)
		//return "Null"
	}
	defer res.Body.Close()
	//fmt.Println("in vmStatus 3 " )
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println("Error in vmStatus ", err)
		//return "Null"
	}
	//fmt.Println("full response: ",string(body))
	//fmt.Println("in vmStatus 4 " )

	_vmstatus := vmStatus{}
	_err := json.Unmarshal(body, &_vmstatus)
	//fmt.Println("in vmStatus 5 " )
	if _err != nil {
		fmt.Println("Error in vmStatus ", _err)
	}
	return _vmstatus.Status
}
func (o ovirt) addvm(c echo.Context) error {
	type AddVMPayment struct {
		Data struct {
			Price struct {
				CPU    float64 `json:"cpu"`
				Mem    float64 `json:"mem"`
				Disk   float64 `json:"disk"`
				Nic    float64 `json:"nic"`
				BW     float64 `json:"bw"`
				SUM    float64 `json:"sum"`
				Period string  `json:"period"`
			} `json:"price"`
			InvoiceUUID string `json:"invoiceUUID"`
		} `json:"data"`
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	var vmname, vmdescr, vmcomment, templatename, cpuSock, cpuCore, cpuThread, mem, Disk, nic, period, extraBW string
	vmname = login(BA).AuthenticatedUser.ID + "-_-" + c.FormValue("VmName")
	vmdescr = c.FormValue("VmDescr")
	vmcomment = c.FormValue("VmComment")
	templatename = c.FormValue("VmTempl")
	cpuThread = c.FormValue("VmCPU")
	Disk = c.FormValue("VmDisk")
	period = c.FormValue("VmPeriod")
	nic = c.FormValue("VmNIC")
	extraBW = c.FormValue("extraBW")
	sshKey := c.FormValue("sshKey")
	rootpass := c.FormValue("rootpass")
	cpuCore = "1"
	cpuSock = "1"
	mem = c.FormValue("VmMem")
	url := OvirtURL + "/ovirt-engine/api/vms"
	method := "POST"
	//TODO: Encrypt this Json
	//	_json := fmt.Sprintf(`
	//{
	//    "name": "%s",
	//    "description": "%s",
	//    "comment": "%s",
	//    "cluster": {
	//        "name": "Default"
	//    },
	//    "template": {
	//        "name": "%s"
	//    },
	//    "cpu": {
	//        "topology": {
	//            "sockets": "%s",
	//            "cores": "%s",
	//            "threads": "%s"
	//        }
	//    },
	//    "memory": "%s",
	//    "memory_policy": {
	//        "ballooning": "true",
	//        "guaranteed": "%s",
	//        "over_commit": {
	//            "percent": "10"
	//        }
	//    }
	//}
	//`, vmname, vmdescr, vmcomment, templatename, cpuSock, cpuCore, cpuThread, mem, mem)
	// Change as task
	//change to task//	payload := strings.NewReader(_json)
	//change to task//	//tr := &http.Transport{
	//change to task//	//	TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	//change to task//	//}
	//change to task//	client := &http.Client{}
	//change to task//	req, err := http.NewRequest(method, url, payload)
	//change to task//	if err != nil {
	//change to task//		fmt.Println(err)
	//change to task//	}
	//change to task//	req.Header.Add("Version", "4")
	//change to task//	req.Header.Add("Accept", "application/json")
	//change to task//	req.Header.Add("Authorization", BA)
	//change to task//	req.Header.Add("Content-Type", "application/json")
	//change to task//	res, err := client.Do(req)
	//change to task//	body, err := ioutil.ReadAll(res.Body)
	//change to task//	//fmt.Println("len: ", len(_json))
	//change to task//	//fmt.Println("res:", res)
	//change to task//	if err != nil || res.StatusCode != 202 {
	//change to task//		resp := _response{
	//change to task//			Origin:  "ovirt-addvm",
	//change to task//			Message: res.Status,
	//change to task//			Code:    1001,
	//change to task//		}
	//change to task//		b, _ := json.MarshalIndent(resp, "", "  ")
	//change to task//		return c.String(http.StatusBadRequest, string(b))
	//change to task//	}
	//change to task//	defer res.Body.Close()
	//addvmresponse := AddVMResponse{}O
	newvm := AddVMRequest{
		URL: url,
		JSON: struct {
			Name        string `json:"name"`
			Description string `json:"description"`
			Comment     string `json:"comment"`
			Cluster     struct {
				Name string `json:"name"`
			} `json:"cluster"`
			Template struct {
				Name string `json:"name"`
			} `json:"template"`
			CPU struct {
				Topology struct {
					Sockets string `json:"sockets"`
					Cores   string `json:"cores"`
					Threads string `json:"threads"`
				} `json:"topology"`
			} `json:"cpu"`
			Memory       string `json:"memory"`
			MemoryPolicy struct {
				Ballooning string `json:"ballooning"`
				Guaranteed string `json:"guaranteed"`
				OverCommit struct {
					Percent string `json:"percent"`
				} `json:"over_commit"`
			} `json:"memory_policy"`
		}{
			Name:        vmname,
			Description: vmdescr,
			Comment:     vmcomment,
			Cluster: struct {
				Name string `json:"name"`
			}{Name: "Default"},
			Template: struct {
				Name string `json:"name"`
			}{Name: templatename},
			CPU: struct {
				Topology struct {
					Sockets string `json:"sockets"`
					Cores   string `json:"cores"`
					Threads string `json:"threads"`
				} `json:"topology"`
			}{
				struct {
					Sockets string `json:"sockets"`
					Cores   string `json:"cores"`
					Threads string `json:"threads"`
				}{
					Sockets: cpuSock,
					Cores:   cpuCore,
					Threads: cpuThread,
				},
			},
			Memory: mem,
			MemoryPolicy: struct {
				Ballooning string `json:"ballooning"`
				Guaranteed string `json:"guaranteed"`
				OverCommit struct {
					Percent string `json:"percent"`
				} `json:"over_commit"`
			}{
				Ballooning: "true",
				Guaranteed: mem,
				OverCommit: struct {
					Percent string `json:"percent"`
				}{Percent: "10"},
			},
		},
		Method:  method,
		Headers: nil,
	}
	newvm.Headers = append(newvm.Headers, struct {
		Name  string `json:"Name"`
		Value string `json:"Value"`
	}{
		Name:  "Accept",
		Value: "application/json",
	})
	newvm.Headers = append(newvm.Headers, struct {
		Name  string `json:"Name"`
		Value string `json:"Value"`
	}{
		Name:  "Authorization",
		Value: BA,
	})
	newvm.Headers = append(newvm.Headers, struct {
		Name  string `json:"Name"`
		Value string `json:"Value"`
	}{
		Name:  "Content-Type",
		Value: "application/json",
	})
	uuid, _ := uuidgen("APIGW-Ovirt-addVMTask")
	//invoiceUUID, _ := uuidgen("APIGW-FakeInvoice")
	CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice, SUM, invoiceUUID := IaaSCreate(login(BA).AuthenticatedUser.ID, period, cpuThread, mem, Disk, nic, extraBW)
	responseInvoiece := AddVMPayment{
		Data: struct {
			Price struct {
				CPU    float64 `json:"cpu"`
				Mem    float64 `json:"mem"`
				Disk   float64 `json:"disk"`
				Nic    float64 `json:"nic"`
				BW     float64 `json:"bw"`
				SUM    float64 `json:"sum"`
				Period string  `json:"period"`
			} `json:"price"`
			InvoiceUUID string `json:"invoiceUUID"`
		}{
			Price: struct {
				CPU    float64 `json:"cpu"`
				Mem    float64 `json:"mem"`
				Disk   float64 `json:"disk"`
				Nic    float64 `json:"nic"`
				BW     float64 `json:"bw"`
				SUM    float64 `json:"sum"`
				Period string  `json:"period"`
			}{
				CPU:    CPUPrice,
				Mem:    memPrice,
				Disk:   StoragePrice,
				Nic:    IPPrice,
				BW:     extraBWPrice,
				SUM:    SUM,
				Period: period,
			},
			InvoiceUUID: invoiceUUID,
		},
		Message: "Done",
		Origin:  "AddVM",
		Code:    1000,
	}
	if len(invoiceUUID) < 5 {
		resp := _response{
			Origin:  "ovirt-addvm",
			Message: "Error on Invoice Calculation",
			Code:    1001,
		}
		b, _ := json.MarshalIndent(resp, "", "  ")
		return c.String(http.StatusBadRequest, string(b))
	}
	//fmt.Println("Invoice: ",invoiceUUID)
	__createVM, _ := json.MarshalIndent(newvm, "", "  ")
	// Add VM Task
	addTask(uuid, string(__createVM), "", "APIGW", "VM Creation for "+claims["name"].(string), invoiceUUID, "0", "0")

	{
		db, err := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
		if err != nil {
			resp := _response{
				Origin:  "ovirt-addvm",
				Message: "Error on connecting db for save add vm result",
				Code:    1001,
			}
			b, _ := json.MarshalIndent(resp, "", "  ")
			return c.String(http.StatusBadRequest, string(b))
		}
		defer db.Close()
		insert, err := db.Query("INSERT INTO service_profile VALUES ( '" + invoiceUUID + "'," +
			"'" + claims["IPAUid"].(string) + "'," +
			"'" + "VM" + "'," +
			"'" + "" + "'," +
			"'" + login(BA).AuthenticatedUser.ID + "'," +
			"NOW()" + "," +
			"NOW() ," +
			"-1" + "," +
			"'" + vmname + "'," +
			"'" + invoiceUUID + "' )")
		defer insert.Close()
		if err != nil {
			fmt.Println("Error in addVM: ", err.Error())
		}

	}

	// Start Task
	{

		url := OvirtURL + "/ovirt-engine/api/vms/" + invoiceUUID + "/start"
		method := "POST"
		nicAddress := "172.20.15.251"
		nicMask := "255.255.255.0"
		nicGW := "172.20.15.1"
		__json := fmt.Sprintf(`
{
	"async":"true",
    "use_cloud_init": "true",
    "vm": {
        "initialization": {
            "authorized_ssh_keys": "%s",
            "host_name": "Sassan.local",
            "user_name": "root",
            "root_password": "%s",
            "nic_configurations": {
                "nic_configuration": [
                    {
                        "name": "eth0",
                        "on_boot": "true",
                        "boot_protocol": "static",
                        "ip": {
                            "address": "%s",
                            "netmask": "%s",
                            "gateway": "%s"
                        }
                    }
                ]
            },
            "dns_servers": "172.20.11.11"
        }
    }
}
`, sshKey, rootpass, nicAddress, nicMask, nicGW)
		sha256 := sha256.Sum256([]byte(invoiceUUID))
		var hashChannel = make(chan []byte, 1)
		hashChannel <- sha256[:]
		___json := encrypt(<-hashChannel, __json)
		startVM := addVMTask{
			URL:     url,
			JSON:    ___json,
			Method:  method,
			Headers: nil,
		}
		startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Version", Value: "4"})
		startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Accept", Value: "application/json"})
		startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Content-Type", Value: "application/json"})
		startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Authorization", Value: BA})

		uuid, _ := uuidgen("APIGW-Ovirt-CloudInit")
		__startVM, _ := json.MarshalIndent(startVM, "", "  ")
		//fmt.Println("StartVMHeaders: ", string(__startVMHeaders))
		addTask(uuid, string(__startVM), "", "APIGW", "VM Initialization", invoiceUUID, "1", "0")
	}
	//resp := _response{
	//	Origin:  "ovirt-addvm",
	//	Message: resposeInvoice
	//	Code:    1000,
	//}
	return c.JSON(http.StatusOK, responseInvoiece)
}
func (o ovirt) listVM(c echo.Context) error {
	type listVMs struct {
		VM []struct {
			Fqdn                 string `json:"fqdn,omitempty"`
			GuestOperatingSystem struct {
				Architecture string `json:"architecture"`
				Codename     string `json:"codename"`
				Distribution string `json:"distribution"`
				Family       string `json:"family"`
				Kernel       struct {
					Version struct {
						Build       string `json:"build"`
						FullVersion string `json:"full_version"`
						Major       string `json:"major"`
						Minor       string `json:"minor"`
						Revision    string `json:"revision"`
					} `json:"version"`
				} `json:"kernel"`
				Version struct {
					FullVersion string `json:"full_version"`
					Major       string `json:"major"`
				} `json:"version"`
			} `json:"guest_operating_system,omitempty"`
			GuestTimeZone struct {
				Name      string `json:"name"`
				UtcOffset string `json:"utc_offset"`
			} `json:"guest_time_zone,omitempty"`
			NextRunConfigurationExists string `json:"next_run_configuration_exists"`
			NumaTuneMode               string `json:"numa_tune_mode"`
			RunOnce                    string `json:"run_once,omitempty"`
			StartTime                  int64  `json:"start_time,omitempty"`
			Status                     string `json:"status"`
			StopTime                   int64  `json:"stop_time"`
			OriginalTemplate           struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"original_template"`
			Template struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"template"`
			Actions struct {
				Link []struct {
					Href string `json:"href"`
					Rel  string `json:"rel"`
				} `json:"link"`
			} `json:"actions"`
			Name        string `json:"name"`
			Description string `json:"description"`
			Comment     string `json:"comment"`
			Href        string `json:"href"`
			ID          string `json:"id"`
			Bios        struct {
				BootMenu struct {
					Enabled string `json:"enabled"`
				} `json:"boot_menu"`
				Type string `json:"type"`
			} `json:"bios"`
			CPU struct {
				Architecture string `json:"architecture"`
				Topology     struct {
					Cores   string `json:"cores"`
					Sockets string `json:"sockets"`
					Threads string `json:"threads"`
				} `json:"topology"`
			} `json:"cpu"`
			Display struct {
				Address       string `json:"address"`
				AllowOverride string `json:"allow_override"`
				Certificate   struct {
					Content      string `json:"content"`
					Organization string `json:"organization"`
					Subject      string `json:"subject"`
				} `json:"certificate"`
				CopyPasteEnabled    string `json:"copy_paste_enabled"`
				DisconnectAction    string `json:"disconnect_action"`
				FileTransferEnabled string `json:"file_transfer_enabled"`
				Monitors            string `json:"monitors"`
				Port                string `json:"port"`
				SecurePort          string `json:"secure_port"`
				SingleQxlPci        string `json:"single_qxl_pci"`
				SmartcardEnabled    string `json:"smartcard_enabled"`
				Type                string `json:"type"`
			} `json:"display"`
			Initialization struct {
				AuthorizedSSHKeys        string `json:"authorized_ssh_keys"`
				CloudInitNetworkProtocol string `json:"cloud_init_network_protocol"`
				CustomScript             string `json:"custom_script"`
				HostName                 string `json:"host_name"`
				NicConfigurations        struct {
				} `json:"nic_configurations"`
				RegenerateSSHKeys string `json:"regenerate_ssh_keys"`
				UserName          string `json:"user_name"`
			} `json:"initialization"`
			Io struct {
				Threads string `json:"threads"`
			} `json:"io"`
			Memory    string `json:"memory"`
			Migration struct {
				AutoConverge string `json:"auto_converge"`
				Compressed   string `json:"compressed"`
				Encrypted    string `json:"encrypted"`
			} `json:"migration"`
			Origin string `json:"origin"`
			Os     struct {
				Boot struct {
					Devices struct {
						Device []string `json:"device"`
					} `json:"devices"`
				} `json:"boot"`
				Type string `json:"type"`
			} `json:"os"`
			Sso struct {
				Methods struct {
					Method []struct {
						ID string `json:"id"`
					} `json:"method"`
				} `json:"methods"`
			} `json:"sso"`
			Stateless string `json:"stateless"`
			Type      string `json:"type"`
			Usb       struct {
				Enabled string `json:"enabled"`
			} `json:"usb"`
			Cluster struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"cluster"`
			Quota struct {
				ID string `json:"id"`
			} `json:"quota"`
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
			CPUShares        string `json:"cpu_shares"`
			CreationTime     int64  `json:"creation_time"`
			DeleteProtected  string `json:"delete_protected"`
			HighAvailability struct {
				Enabled  string `json:"enabled"`
				Priority string `json:"priority"`
			} `json:"high_availability"`
			LargeIcon struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"large_icon"`
			MemoryPolicy struct {
				Guaranteed string `json:"guaranteed"`
				Max        string `json:"max"`
			} `json:"memory_policy"`
			MigrationDowntime  string `json:"migration_downtime"`
			MultiQueuesEnabled string `json:"multi_queues_enabled"`
			SmallIcon          struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"small_icon"`
			StartPaused                 string `json:"start_paused"`
			StorageErrorResumeBehaviour string `json:"storage_error_resume_behaviour"`
			TimeZone                    struct {
				Name string `json:"name"`
			} `json:"time_zone"`
			CPUProfile struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"cpu_profile"`
			StopReason string `json:"stop_reason,omitempty"`
		} `json:"vm"`
	}
	type listVMResponse struct {
		Data []struct {
			Fqdn        string `json:"fqdn"`
			StartTime   int64  `json:"start_time"`
			Status      string `json:"status"`
			Name        string `json:"name"`
			Description string `json:"description"`
			Comment     string `json:"comment"`
			ID          string `json:"id"`
			CPU         struct {
				Topology struct {
					Cores   string `json:"cores"`
					Sockets string `json:"sockets"`
					Threads string `json:"threads"`
				} `json:"topology"`
			} `json:"cpu"`
			Memory       string `json:"memory"`
			CreationTime int64  `json:"creation_time"`
			Disk         []struct {
				Name       string `json:"Name"`
				TotalSize  string `json:"TotalSize"`
				ActualSize string `json:"ActualSize"`
			} `json:"Disk"`
			NIC []struct {
				Mac             string `json:"mac"`
				IPv4            string `json:"IPv4"`
				IPv6            string `json:"IPv6"`
				ReportedDevices struct {
					Mac  string `json:"mac"`
					IPv4 string `json:"IPv4"`
					IPv6 string `json:"IPv6"`
				} `json:"reported_devices"`
			} `json:"NIC"`
		} `json:"vm"`
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}

	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	url := OvirtURL + "/ovirt-engine/api/vms"
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)

	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	//fmt.Printf("%s",body)
	//b, _ := json.MarshalIndent(body, "", "  ")
	_VMLists := listVMs{}
	err = json.Unmarshal(body, &_VMLists)
	_listVMResponse := listVMResponse{
		Data:    nil,
		Message: "Done",
		Origin:  "ListVMs",
		Code:    1000,
	}
	_Data := _listVMResponse.Data
	y := struct {
		Fqdn        string `json:"fqdn"`
		StartTime   int64  `json:"start_time"`
		Status      string `json:"status"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Comment     string `json:"comment"`
		ID          string `json:"id"`
		CPU         struct {
			Topology struct {
				Cores   string `json:"cores"`
				Sockets string `json:"sockets"`
				Threads string `json:"threads"`
			} `json:"topology"`
		} `json:"cpu"`
		Memory       string `json:"memory"`
		CreationTime int64  `json:"creation_time"`
		Disk         []struct {
			Name       string `json:"Name"`
			TotalSize  string `json:"TotalSize"`
			ActualSize string `json:"ActualSize"`
		} `json:"Disk"`
		NIC []struct {
			Mac             string `json:"mac"`
			IPv4            string `json:"IPv4"`
			IPv6            string `json:"IPv6"`
			ReportedDevices struct {
				Mac  string `json:"mac"`
				IPv4 string `json:"IPv4"`
				IPv6 string `json:"IPv6"`
			} `json:"reported_devices"`
		} `json:"NIC"`
	}{}
	//fmt.Println("Customer UUID:",login(BA).AuthenticatedUser.ID)
	for _, v := range _VMLists.VM {
		y.ID = v.ID
		y.Fqdn = v.Fqdn
		y.StartTime = v.StartTime
		y.Status = v.Status
		y.Name = v.Name
		if len(v.Name) > 35 {
			y.Name = v.Name[len(login(BA).AuthenticatedUser.ID)+3:]
		}
		y.Description = v.Description
		y.Comment = v.Comment
		y.CPU.Topology.Cores = v.CPU.Topology.Cores
		y.CPU.Topology.Sockets = v.CPU.Topology.Sockets
		y.CPU.Topology.Threads = v.CPU.Topology.Threads
		y.Memory = v.Memory
		y.CreationTime = v.CreationTime
		y.NIC = listNIC(v.ID, BA)
		y.Disk = listDisks(v.ID, BA)

		_Data = append(_Data, y)
	}
	_listVMResponse.Data = _Data
	if err != nil {
		//fmt.Println("Error on ListVM",err)
		//return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice
		resp := _response{
			Origin:  "ovirt-listvms",
			Message: "Error in Parsing listVMs",
			Code:    1001,
		}
		return c.JSON(http.StatusInternalServerError, resp)
	}
	//fmt.Printf("%s", body)
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, _listVMResponse)
	//return c.String(http.StatusOK, string(b))
}
func (o ovirt) StartVM(c echo.Context) error {
	vmuuid := c.FormValue("VmUUID")
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	url := OvirtURL + "/ovirt-engine/api/vms/" + vmuuid + "/start"
	method := "POST"
	__json := "{\"async\":\"true\"}"
	sha256 := sha256.Sum256([]byte(vmuuid))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- sha256[:]
	___json := encrypt(<-hashChannel, __json)
	startVM := addVMTask{
		URL:     url,
		JSON:    ___json,
		Method:  method,
		Headers: nil,
	}
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Version", Value: "4"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Accept", Value: "application/json"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Content-Type", Value: "application/json"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Authorization", Value: BA})

	//req.Header.Add("Version", "4")
	//req.Header.Add("Accept", "application/json")
	//req.Header.Add("Authorization", BA)
	//req.Header.Add("Content-Type", "application/json")
	//
	//res, err := client.Do(req)
	//defer res.Body.Close()
	uuid, _ := uuidgen("APIGW-Ovirt")
	__startVM, _ := json.MarshalIndent(startVM, "", "  ")
	//fmt.Println("StartVMHeaders: ", string(__startVMHeaders))
	addTask(uuid, string(__startVM), "", "APIGW", "VM Start", vmuuid, "1", "1")

	resp := _response{
		Origin:  "ovirt-StartVM",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, resp)
	//return c.String(http.StatusOK, string(b))
}
func (o ovirt) StopVM(c echo.Context) error {
	vmuuid := c.FormValue("VmUUID")
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	url := OvirtURL + "/ovirt-engine/api/vms/" + vmuuid + "/shutdown"
	method := "POST"
	__json := "{\"async\":\"true\"}"
	sha256 := sha256.Sum256([]byte(vmuuid))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- sha256[:]
	___json := encrypt(<-hashChannel, __json)

	payload := strings.NewReader(___json)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)
	res, err := client.Do(req)
	if err != nil {
		//return c.String(http.StatusBadRequest, "Error"+err.Error())
		return c.JSON(http.StatusOK, "Error"+err.Error())
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	fmt.Println("Resp:" + string(body))

	//req.Header.Add("Version", "4")
	//req.Header.Add("Accept", "application/json")
	//req.Header.Add("Authorization", BA)
	//req.Header.Add("Content-Type", "application/json")
	//
	//res, err := client.Do(req)
	//defer res.Body.Close()
	//uuid, _ := uuidgen("APIGW-Ovirt")
	//__startVM, _ := json.MarshalIndent(req, "", "  ")
	//fmt.Println("StartVMHeaders: ", string(__startVMHeaders))
	//addTask(uuid, string(__startVM), "", "APIGW", "VM Start", vmuuid, "1", "1")

	resp := _response{
		Origin:  "ovirt-StopVM",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, resp)
	//return c.String(http.StatusOK, string(b))
}
func (o ovirt) RebootVM(c echo.Context) error {
	vmuuid := c.FormValue("VmUUID")
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	url := OvirtURL + "/ovirt-engine/api/vms/" + vmuuid + "/reboot"
	method := "POST"
	__json := "{\"async\":\"true\"}"
	sha256 := sha256.Sum256([]byte(vmuuid))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- sha256[:]
	___json := encrypt(<-hashChannel, __json)
	startVM := addVMTask{
		URL:     url,
		JSON:    ___json,
		Method:  method,
		Headers: nil,
	}
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Version", Value: "4"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Accept", Value: "application/json"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Content-Type", Value: "application/json"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Authorization", Value: BA})

	//req.Header.Add("Version", "4")
	//req.Header.Add("Accept", "application/json")
	//req.Header.Add("Authorization", BA)
	//req.Header.Add("Content-Type", "application/json")
	//
	//res, err := client.Do(req)
	//defer res.Body.Close()
	uuid, _ := uuidgen("APIGW-Ovirt")
	__startVM, _ := json.MarshalIndent(startVM, "", "  ")
	//fmt.Println("StartVMHeaders: ", string(__startVMHeaders))
	addTask(uuid, string(__startVM), "", "APIGW", "VM Start", vmuuid, "1", "1")

	resp := _response{
		Origin:  "ovirt-RebootVM",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (o ovirt) PowerOffVM(c echo.Context) error {
	vmuuid := c.FormValue("VmUUID")
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	url := OvirtURL + "/ovirt-engine/api/vms/" + vmuuid + "/stop"
	method := "POST"
	__json := "{\"async\":\"true\"}"
	sha256 := sha256.Sum256([]byte(vmuuid))
	var hashChannel = make(chan []byte, 1)
	hashChannel <- sha256[:]
	___json := encrypt(<-hashChannel, __json)
	startVM := addVMTask{
		URL:     url,
		JSON:    ___json,
		Method:  method,
		Headers: nil,
	}
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Version", Value: "4"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Accept", Value: "application/json"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Content-Type", Value: "application/json"})
	startVM.Headers = append(startVM.Headers, TaskHeader{Name: "Authorization", Value: BA})

	//req.Header.Add("Version", "4")
	//req.Header.Add("Accept", "application/json")
	//req.Header.Add("Authorization", BA)
	//req.Header.Add("Content-Type", "application/json")
	//
	//res, err := client.Do(req)
	//defer res.Body.Close()
	uuid, _ := uuidgen("APIGW-Ovirt")
	__startVM, _ := json.MarshalIndent(startVM, "", "  ")
	//fmt.Println("StartVMHeaders: ", string(__startVMHeaders))
	addTask(uuid, string(__startVM), "", "APIGW", "VM Start", vmuuid, "1", "1")

	resp := _response{
		Origin:  "ovirt-PowerOffVM",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (o ovirt) ResetVM(c echo.Context) error {
	resp := _response{
		Origin:  "ovirt-ResetVM",
		Message: "not implemented",
		Code:    1003,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	return c.JSON(http.StatusOK, resp)
	//return c.String(http.StatusOK, string(b))

}
func (o ovirt) AddNIC(c echo.Context) error {
	resp := _response{
		Origin:  "ovirt-AddNIC",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (o ovirt) AddDisk(c echo.Context) error {
	resp := _response{
		Origin:  "ovirt-AddDisk",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (o ovirt) EditVM(c echo.Context) error {
	resp := _response{
		Origin:  "ovirt-EditVM",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func (o ovirt) ResetPassword(c echo.Context) error {
	resp := _response{
		Origin:  "ovirt-ResetPassword",
		Message: "not implemented",
		Code:    1003,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func createVM(invoice_uuid string, apiJson string, uuid string) {
	type AddVMResponse struct {
		NextRunConfigurationExists string `json:"next_run_configuration_exists"`
		NumaTuneMode               string `json:"numa_tune_mode"`
		Status                     string `json:"status"`
		StopTime                   int64  `json:"stop_time"`
		OriginalTemplate           struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"original_template"`
		Template struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"template"`
		Actions struct {
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
		} `json:"actions"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Comment     string `json:"comment"`
		Href        string `json:"href"`
		ID          string `json:"id"`
		Bios        struct {
			BootMenu struct {
				Enabled string `json:"enabled"`
			} `json:"boot_menu"`
			Type string `json:"type"`
		} `json:"bios"`
		Console struct {
			Enabled string `json:"enabled"`
		} `json:"console"`
		CPU struct {
			Architecture string `json:"architecture"`
			Topology     struct {
				Cores   string `json:"cores"`
				Sockets string `json:"sockets"`
				Threads string `json:"threads"`
			} `json:"topology"`
		} `json:"cpu"`
		Display struct {
			AllowOverride       string `json:"allow_override"`
			CopyPasteEnabled    string `json:"copy_paste_enabled"`
			DisconnectAction    string `json:"disconnect_action"`
			FileTransferEnabled string `json:"file_transfer_enabled"`
			Monitors            string `json:"monitors"`
			SingleQxlPci        string `json:"single_qxl_pci"`
			SmartcardEnabled    string `json:"smartcard_enabled"`
			Type                string `json:"type"`
		} `json:"display"`
		Initialization struct {
			AuthorizedSSHKeys        string `json:"authorized_ssh_keys"`
			CloudInitNetworkProtocol string `json:"cloud_init_network_protocol"`
			CustomScript             string `json:"custom_script"`
			HostName                 string `json:"host_name"`
			NicConfigurations        struct {
			} `json:"nic_configurations"`
			RegenerateSSHKeys string `json:"regenerate_ssh_keys"`
			UserName          string `json:"user_name"`
		} `json:"initialization"`
		Io struct {
			Threads string `json:"threads"`
		} `json:"io"`
		Memory    string `json:"memory"`
		Migration struct {
			AutoConverge string `json:"auto_converge"`
			Compressed   string `json:"compressed"`
			Encrypted    string `json:"encrypted"`
		} `json:"migration"`
		Origin string `json:"origin"`
		Os     struct {
			Boot struct {
				Devices struct {
					Device []string `json:"device"`
				} `json:"devices"`
			} `json:"boot"`
			Type string `json:"type"`
		} `json:"os"`
		Sso struct {
			Methods struct {
				Method []struct {
					ID string `json:"id"`
				} `json:"method"`
			} `json:"methods"`
		} `json:"sso"`
		Stateless string `json:"stateless"`
		Type      string `json:"type"`
		Usb       struct {
			Enabled string `json:"enabled"`
		} `json:"usb"`
		Cluster struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"cluster"`
		Quota struct {
			ID string `json:"id"`
		} `json:"quota"`
		CreationStatus string `json:"creation_status"`
		Link           []struct {
			Href string `json:"href"`
			Rel  string `json:"rel"`
		} `json:"link"`
		CPUShares        string `json:"cpu_shares"`
		CreationTime     int64  `json:"creation_time"`
		DeleteProtected  string `json:"delete_protected"`
		HighAvailability struct {
			Enabled  string `json:"enabled"`
			Priority string `json:"priority"`
		} `json:"high_availability"`
		LargeIcon struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"large_icon"`
		MemoryPolicy struct {
			Ballooning string `json:"ballooning"`
			Guaranteed string `json:"guaranteed"`
			Max        string `json:"max"`
		} `json:"memory_policy"`
		MigrationDowntime  string `json:"migration_downtime"`
		MultiQueuesEnabled string `json:"multi_queues_enabled"`
		RngDevice          struct {
			Source string `json:"source"`
		} `json:"rng_device"`
		SmallIcon struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"small_icon"`
		SoundcardEnabled            string `json:"soundcard_enabled"`
		StartPaused                 string `json:"start_paused"`
		StorageErrorResumeBehaviour string `json:"storage_error_resume_behaviour"`
		TimeZone                    struct {
			Name string `json:"name"`
		} `json:"time_zone"`
		VirtioScsi struct {
			Enabled string `json:"enabled"`
		} `json:"virtio_scsi"`
		CPUProfile struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"cpu_profile"`
	}

	_createVM := AddVMRequest{}
	//fmt.Println(apiJson)
	_err := json.Unmarshal([]byte(apiJson), &_createVM)
	if _err != nil {
		fmt.Println("Error in VMCreation step 1: ", _err.Error())
	}
	addvmresponse := AddVMResponse{}
	var body []byte
	{
		url := _createVM.URL
		method := _createVM.Method
		__json := _createVM.JSON
		client := &http.Client{}
		_json, _ := json.Marshal(__json)
		payload := strings.NewReader(string(_json))
		//payload := __json
		req, err := http.NewRequest(method, url, payload)
		if err != nil {
			fmt.Println("Error in VMCreation  step 2: ", err.Error())
		}
		_headers := _createVM.Headers
		for _, v := range _headers {
			req.Header.Add(v.Name, v.Value)
		}
		if err != nil {
			fmt.Println("Error in VMCreation  step 3: ", err.Error())
		}
		res, err := client.Do(req)
		defer res.Body.Close()
		body, _ = ioutil.ReadAll(res.Body)
	}
	//body := runAPICall(_createVM)
	err := json.Unmarshal(body, &addvmresponse)
	if err != nil {
		fmt.Println("Error in VMCreation  step 4: ", err.Error())
	}
	toggleTask(uuid, 0)
	// find related VMInitialization Task
	//ruuid := ""
	{
		db, err := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
		if err != nil {
			fmt.Println("Error in VMCreation step 3: ", _err.Error())
		}
		//defer db.Close()
		//results, err := db.Query("SELECT uuid as UUID ,task_apiCall as TaskAPICall , cron_expression as CronExpression , related_uuid as Ruuid, type FROM scheduler where  related_invoice=" + invoice_uuid + " and type=1")
		//type Task struct {
		//	UUID           string `json:"uuid"`
		//	TaskAPICall    string `json:"taskapicall"`
		//	Ruuid          string `json:"ruuid"`
		//	CronExpression string `json:"cronexpression"`
		//	Type           string `json:"type"`
		//}
		//for results.Next() {
		//	var res Task
		//	err = results.Scan(&res.UUID, &res.TaskAPICall, &res.CronExpression, &res.Ruuid, &res.Type)
		//	ruuid = res.UUID
		//	break
		//}
		//update UUID and status
		update2, err := db.Query("update service_profile set uuid='" + addvmresponse.ID + "' , active=1 where related_invoice='" + invoice_uuid + "'")
		update, err := db.Query("update scheduler set related_uuid='" + addvmresponse.ID + "' , active=1 where related_uuid='" + invoice_uuid + "' and type=1")
		defer update.Close()
		defer update2.Close()
		//toggleTask(ruuid, 1)
	}

}
func VMInitialization(relatedUuid string, apiCall string, uuid string) {
	iaas := &ovirt{}

	//fmt.Println("VM :", relatedUuid)
	status := iaas.vmStatus(relatedUuid)
	fmt.Println("VM :", relatedUuid, " is now: ", status)
	if status == "down" {
		//fmt.Println("APICall: ", apiCall)
		startVM := addVMTask{}
		//b, _ := json.Marshal(apiCall)
		_err := json.Unmarshal([]byte(apiCall), &startVM)
		if _err != nil {
			fmt.Println("Error in VMInitialization: ", _err.Error())
		}
		//fmt.Println("calling initialization for VM :", relatedUuid)
		words := strings.Split(startVM.URL, "/")
		//fmt.Println("Invoice : ", words[6])
		_sha256 := sha256.Sum256([]byte(words[6]))
		var hashChannel_ = make(chan []byte, 1)
		hashChannel_ <- _sha256[:]
		//fmt.Println(" startVM.JSON: ", startVM.JSON)
		startVM.JSON = decrypt(<-hashChannel_, startVM.JSON)
		//fmt.Println("decrypted json: ",startVM.JSON)
		startVM.URL = OvirtURL + "/ovirt-engine/api/vms/" + relatedUuid + "/start"
		//fmt.Println("Start URL: ", startVM.URL)
		//fmt.Println("Initialize JSON: ", decrypt(<-hashChannel_, startVM.JSON))
		runAPICall(startVM)
		toggleTask(uuid, 0)
	}
}
func vmStatistics(BA string, VMUUID string) (string, float64, float64, error) {
	//ram,cpu,storage
	var _disk []string
	{
		type DiskAttachments struct {
			DiskAttachment []struct {
				Active              string `json:"active"`
				Bootable            string `json:"bootable"`
				Interface           string `json:"interface"`
				LogicalName         string `json:"logical_name"`
				PassDiscard         string `json:"pass_discard"`
				ReadOnly            string `json:"read_only"`
				UsesScsiReservation string `json:"uses_scsi_reservation"`
				Disk                struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"disk"`
				VM struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"vm"`
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"disk_attachment"`
		}

		url := OvirtURL + "/ovirt-engine/api/vms/" + VMUUID + "/diskattachments"
		//fmt.Println("Url:" ,url)
		method := "GET"

		client := &http.Client{}
		req, err := http.NewRequest(method, url, nil)

		if err != nil {
			return "", -1, -1, errors.New("unexpected Error")
		}
		req.Header.Add("Version", "4")
		req.Header.Add("Accept", "application/json")
		req.Header.Add("Authorization", BA)

		res, err := client.Do(req)
		defer res.Body.Close()
		body, err := ioutil.ReadAll(res.Body)
		diskattachments := DiskAttachments{}
		_err := json.Unmarshal(body, &diskattachments)
		if _err != nil {
			fmt.Println("Error in vmStatistics 1: ", _err)
		}
		for _, v := range diskattachments.DiskAttachment {
			url := OvirtURL + "/ovirt-engine/api/disks/" + v.Disk.ID
			type DiskAttachment struct {
				ActualSize      string `json:"actual_size"`
				Alias           string `json:"alias"`
				Backup          string `json:"backup"`
				ContentType     string `json:"content_type"`
				Format          string `json:"format"`
				ImageID         string `json:"image_id"`
				PropagateErrors string `json:"propagate_errors"`
				ProvisionedSize string `json:"provisioned_size"`
				QcowVersion     string `json:"qcow_version"`
				Shareable       string `json:"shareable"`
				Sparse          string `json:"sparse"`
				Status          string `json:"status"`
				StorageType     string `json:"storage_type"`
				TotalSize       string `json:"total_size"`
				WipeAfterDelete string `json:"wipe_after_delete"`
				DiskProfile     struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"disk_profile"`
				Quota struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"quota"`
				StorageDomains struct {
					StorageDomain []struct {
						Href string `json:"href"`
						ID   string `json:"id"`
					} `json:"storage_domain"`
				} `json:"storage_domains"`
				Actions struct {
					Link []struct {
						Href string `json:"href"`
						Rel  string `json:"rel"`
					} `json:"link"`
				} `json:"actions"`
				Name        string `json:"name"`
				Description string `json:"description"`
				Href        string `json:"href"`
				ID          string `json:"id"`
				Link        []struct {
					Href string `json:"href"`
					Rel  string `json:"rel"`
				} `json:"link"`
			}
			//fmt.Println("Url:" ,url)
			method := "GET"

			client := &http.Client{}
			req, _ := http.NewRequest(method, url, nil)

			//if err != nil {
			//	return "Null"
			//}
			req.Header.Add("Version", "4")
			req.Header.Add("Accept", "application/json")
			req.Header.Add("Authorization", BA)

			res, _ := client.Do(req)
			defer res.Body.Close()
			body, _ := ioutil.ReadAll(res.Body)

			//fmt.Println("full response: ",string(body))
			disk := DiskAttachment{}
			_err := json.Unmarshal(body, &disk)
			if _err != nil {
				fmt.Println("Error in vmStatistics 2 : ", _err)
			}
			_disk = append(_disk, disk.ProvisionedSize)

			//_disk = D_disk + "" + disk.ProvisionedSize+" "
		}

	}
	url := OvirtURL + "/ovirt-engine/api/vms/" + VMUUID + "/statistics"
	//fmt.Println("Url:" ,url)
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		return "", -1, -1, errors.New("unexpected Error")
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	fmt.Println("Code: ", res.StatusCode)
	if err != nil || res.StatusCode == 404 {
		return "", -1, -1, errors.New("unexpected Error")
	}
	//fmt.Println("full response: ", string(body))
	_vmstatistics := VMStatistics{}
	_err := json.Unmarshal(body, &_vmstatistics)
	if _err != nil {
		fmt.Println("Error in vmStatistics 3: ", _err)
	}
	cpuUUID := _vmstatistics.Statistic[4].ID
	memUsedUUID := _vmstatistics.Statistic[1].ID
	memTotalUUID := _vmstatistics.Statistic[0].ID
	//fmt.Println(memUsedUUID)
	var cpu, memUsed, memTotal string
	type ItemUsage struct {
		Kind   string `json:"kind"`
		Type   string `json:"type"`
		Unit   string `json:"unit"`
		Values struct {
			Value []struct {
				Datum float64 `json:"datum"`
			} `json:"value"`
		} `json:"values"`
		VM struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"vm"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Href        string `json:"href"`
		ID          string `json:"id"`
	}
	{
		url := OvirtURL + "/ovirt-engine/api/vms/" + VMUUID + "/statistics/" + cpuUUID
		//fmt.Println("Url:" ,url)
		method := "GET"

		client := &http.Client{}
		req, err := http.NewRequest(method, url, nil)

		if err != nil {
			return "", -1, -1, errors.New("unexpected Error")
		}
		req.Header.Add("Version", "4")
		req.Header.Add("Accept", "application/json")
		req.Header.Add("Authorization", BA)

		res, err := client.Do(req)
		defer res.Body.Close()
		body, err := ioutil.ReadAll(res.Body)
		cpuUsage := ItemUsage{}
		_err := json.Unmarshal(body, &cpuUsage)
		if _err != nil {
			fmt.Println("Error in vmStatistics 4 ", _err)
		}
		cpu = fmt.Sprintf("%f", cpuUsage.Values.Value[0].Datum)
	}
	{
		url := OvirtURL + "/ovirt-engine/api/vms/" + VMUUID + "/statistics/" + memUsedUUID
		//fmt.Println("Url:" ,url)
		method := "GET"

		client := &http.Client{}
		req, err := http.NewRequest(method, url, nil)

		if err != nil {
			return "", -1, -1, errors.New("unexpected Error")
		}
		req.Header.Add("Version", "4")
		req.Header.Add("Accept", "application/json")
		req.Header.Add("Authorization", BA)

		res, err := client.Do(req)
		defer res.Body.Close()
		body, err := ioutil.ReadAll(res.Body)
		memUsage := ItemUsage{}
		_err := json.Unmarshal(body, &memUsage)
		if _err != nil {
			fmt.Println("Error in vmStatistics 5: ", _err)
		}
		memUsed = fmt.Sprintf("%f", memUsage.Values.Value[0].Datum)
	}
	{
		url := OvirtURL + "/ovirt-engine/api/vms/" + VMUUID + "/statistics/" + memTotalUUID
		//fmt.Println("Url:" ,url)
		method := "GET"

		client := &http.Client{}
		req, err := http.NewRequest(method, url, nil)

		if err != nil {
			return "", -1, -1, errors.New("unexpected Error")
		}
		req.Header.Add("Version", "4")
		req.Header.Add("Accept", "application/json")
		req.Header.Add("Authorization", BA)

		res, err := client.Do(req)
		defer res.Body.Close()
		body, err := ioutil.ReadAll(res.Body)
		memUsage := ItemUsage{}
		_err := json.Unmarshal(body, &memUsage)
		if _err != nil {
			fmt.Println("Error in vmStatistics 6: ", _err)
		}
		memTotal = fmt.Sprintf("%f", memUsage.Values.Value[0].Datum)
	}
	//fmt.Println("CPU:" ,cpu)
	//fmt.Println("MEM:", memUsed)
	//fmt.Println("MEM:", memTotal)
	_memusage, _ := strconv.ParseFloat(memUsed, 32)
	_memtotal, _ := strconv.ParseFloat(memTotal, 32)
	mem := _memusage / _memtotal

	_cpu, _ := strconv.ParseFloat(cpu, 64)
	return strings.Join(_disk, ", "), _cpu, mem, nil

}
func (o ovirt) vmDetails(c echo.Context) error {
	//name,...,traffic,ip,status
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	uuid := c.FormValue("uuid")
	if len(uuid) < 5 {
		resp := _response{
			Origin:  "vmDetails",
			Message: "Missing UUID",
			Code:    1001,
		}
		return c.JSON(http.StatusNotFound, resp)
	}
	type vmStatus struct {
		NextRunConfigurationExists string `json:"next_run_configuration_exists"`
		NumaTuneMode               string `json:"numa_tune_mode"`
		Status                     string `json:"status"`
		StopTime                   int64  `json:"stop_time"`
		OriginalTemplate           struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"original_template"`
		Template struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"template"`
		Actions struct {
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
		} `json:"actions"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Comment     string `json:"comment"`
		Href        string `json:"href"`
		ID          string `json:"id"`
		Bios        struct {
			BootMenu struct {
				Enabled string `json:"enabled"`
			} `json:"boot_menu"`
			Type string `json:"type"`
		} `json:"bios"`
		CPU struct {
			Architecture string `json:"architecture"`
			Topology     struct {
				Cores   string `json:"cores"`
				Sockets string `json:"sockets"`
				Threads string `json:"threads"`
			} `json:"topology"`
		} `json:"cpu"`
		Display struct {
			AllowOverride       string `json:"allow_override"`
			CopyPasteEnabled    string `json:"copy_paste_enabled"`
			DisconnectAction    string `json:"disconnect_action"`
			FileTransferEnabled string `json:"file_transfer_enabled"`
			Monitors            string `json:"monitors"`
			SingleQxlPci        string `json:"single_qxl_pci"`
			SmartcardEnabled    string `json:"smartcard_enabled"`
			Type                string `json:"type"`
		} `json:"display"`
		Initialization struct {
			AuthorizedSSHKeys        string `json:"authorized_ssh_keys"`
			CloudInitNetworkProtocol string `json:"cloud_init_network_protocol"`
			CustomScript             string `json:"custom_script"`
			HostName                 string `json:"host_name"`
			NicConfigurations        struct {
			} `json:"nic_configurations"`
			RegenerateSSHKeys string `json:"regenerate_ssh_keys"`
			UserName          string `json:"user_name"`
		} `json:"initialization"`
		Io struct {
			Threads string `json:"threads"`
		} `json:"io"`
		Memory    string `json:"memory"`
		Migration struct {
			AutoConverge string `json:"auto_converge"`
			Compressed   string `json:"compressed"`
			Encrypted    string `json:"encrypted"`
		} `json:"migration"`
		Origin string `json:"origin"`
		Os     struct {
			Boot struct {
				Devices struct {
					Device []string `json:"device"`
				} `json:"devices"`
			} `json:"boot"`
			Type string `json:"type"`
		} `json:"os"`
		Sso struct {
			Methods struct {
				Method []struct {
					ID string `json:"id"`
				} `json:"method"`
			} `json:"methods"`
		} `json:"sso"`
		Stateless string `json:"stateless"`
		Type      string `json:"type"`
		Usb       struct {
			Enabled string `json:"enabled"`
		} `json:"usb"`
		Cluster struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"cluster"`
		Quota struct {
			ID string `json:"id"`
		} `json:"quota"`
		Link []struct {
			Href string `json:"href"`
			Rel  string `json:"rel"`
		} `json:"link"`
		CPUShares        string `json:"cpu_shares"`
		CreationTime     int64  `json:"creation_time"`
		DeleteProtected  string `json:"delete_protected"`
		HighAvailability struct {
			Enabled  string `json:"enabled"`
			Priority string `json:"priority"`
		} `json:"high_availability"`
		LargeIcon struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"large_icon"`
		MemoryPolicy struct {
			Ballooning string `json:"ballooning"`
			Guaranteed string `json:"guaranteed"`
			Max        string `json:"max"`
		} `json:"memory_policy"`
		MigrationDowntime  string `json:"migration_downtime"`
		MultiQueuesEnabled string `json:"multi_queues_enabled"`
		PlacementPolicy    struct {
			Affinity string `json:"affinity"`
			Hosts    struct {
				Host []struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"host"`
			} `json:"hosts"`
		} `json:"placement_policy"`
		SmallIcon struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"small_icon"`
		StartPaused                 string `json:"start_paused"`
		StorageErrorResumeBehaviour string `json:"storage_error_resume_behaviour"`
		TimeZone                    struct {
			Name string `json:"name"`
		} `json:"time_zone"`
		CPUProfile struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"cpu_profile"`
	}
	//url := "https://ovirt-cl.zi-tel.com/ovirt-engine/api/vms/c1a44128-6c6c-406b-99d8-4a68a99380c9"
	url := OvirtURL + "/ovirt-engine/api/vms/" + uuid
	//fmt.Println("Url:" ,url)
	method := "GET"

	client := &http.Client{}
	req, _ := http.NewRequest(method, url, nil)

	//if err != nil {
	//	return "Null"
	//}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, _ := client.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	//fmt.Println("full response: ",string(body))
	_vmstatus := vmStatus{}
	_err := json.Unmarshal(body, &_vmstatus)
	if _err != nil {
		resp := _response{
			Origin:  "vmDetails",
			Message: "Not Found",
			Code:    1001,
		}
		return c.JSON(http.StatusNotFound, resp)
	}
	disk, cpu, ram, err := vmStatistics(BA, uuid)
	if err != nil {
		fmt.Println("Error in vmDetails 2 : ", err)
		resp := _response{
			Origin:  "vmDetails",
			Message: "Unexpected Error",
			Code:    1001,
		}
		return c.JSON(http.StatusInternalServerError, resp)
	}
	type AutoGenerated struct {
		Message struct {
			Disk       string `json:"Disk"`
			Memory     string `json:"Memory"`
			CPU        string `json:"CPU"`
			NetAddress string `json:"NetAddress"`
			Traffic    string `json:"Traffic"`
			Status     string `json:"Status"`
			Name       string `json:"Name"`
		} `json:"message"`
		Origin string `json:"origin"`
		Code   int    `json:"code"`
	}
	resp := AutoGenerated{
		Message: struct {
			Disk       string `json:"Disk"`
			Memory     string `json:"Memory"`
			CPU        string `json:"CPU"`
			NetAddress string `json:"NetAddress"`
			Traffic    string `json:"Traffic"`
			Status     string `json:"Status"`
			Name       string `json:"Name"`
		}{
			Disk:       disk,
			Memory:     fmt.Sprintf("%f", ram),
			CPU:        fmt.Sprintf("%f", cpu),
			NetAddress: "",
			Traffic:    "",
			Status:     _vmstatus.Status,
			Name:       _vmstatus.Name,
		},
		Origin: "vmDetails",
		Code:   1000,
	}
	return c.JSON(http.StatusOK, resp)
	//return _vmstatus.Status, _vmstatus.Name, disk, cpu, ram
}
func (o ovirt) ovirtPayment(c echo.Context) error {
	invoiceUuid := c.FormValue("invoiceUuid")
	db, err := sql.Open("mysql", MySQLUSER+":"+MySQLPASS+"@tcp(127.0.0.1:3306)/zicloud")
	//results, err := db.Query("SELECT uuid as UUID ,task_apiCall as TaskAPICall , cron_expression as CronExpression , related_uuid as Ruuid, type FROM scheduler where active=1")
	///TODO: check duplicate payment confirmation by Invoice table
	if err != nil {
	}
	update, err := db.Query("update scheduler set active='1' where related_uuid='" + invoiceUuid + "' and type=0")
	defer db.Close()
	if err != nil {
	}
	defer update.Close()
	resp := _response{
		Origin:  "ovirt-ovirtPayment",
		Message: "Done",
		Code:    1000,
	}
	//b, _ := json.MarshalIndent(resp, "", "  ")
	//return c.String(http.StatusOK, string(b))
	return c.JSON(http.StatusOK, resp)
}
func listNIC(VMUUID string, BA string) []struct {
	Mac             string `json:"mac"`
	IPv4            string `json:"IPv4"`
	IPv6            string `json:"IPv6"`
	ReportedDevices struct {
		Mac  string `json:"mac"`
		IPv4 string `json:"IPv4"`
		IPv6 string `json:"IPv6"`
	} `json:"reported_devices"`
} {
	type NICList struct {
		NIC []struct {
			Mac             string `json:"mac"`
			IPv4            string `json:"IPv4"`
			IPv6            string `json:"IPv6"`
			ReportedDevices struct {
				Mac  string `json:"mac"`
				IPv4 string `json:"IPv4"`
				IPv6 string `json:"IPv6"`
			} `json:"reported_devices"`
		} `json:"NIC"`
	}

	type VMNIC struct {
		Nic []struct {
			Interface string `json:"interface"`
			Linked    string `json:"linked"`
			Mac       struct {
				Address string `json:"address"`
			} `json:"mac"`
			Plugged         string `json:"plugged"`
			ReportedDevices struct {
				ReportedDevice []struct {
					Ips struct {
						IP []struct {
							Address string `json:"address"`
							Version string `json:"version"`
						} `json:"ip"`
					} `json:"ips"`
					Mac struct {
						Address string `json:"address"`
					} `json:"mac"`
					Type        string `json:"type"`
					Name        string `json:"name"`
					Description string `json:"description"`
					Href        string `json:"href"`
					ID          string `json:"id"`
				} `json:"reported_device"`
			} `json:"reported_devices"`
			VnicProfile struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"vnic_profile"`
			Actions struct {
				Link []struct {
					Href string `json:"href"`
					Rel  string `json:"rel"`
				} `json:"link"`
			} `json:"actions"`
			Name string `json:"name"`
			Href string `json:"href"`
			ID   string `json:"id"`
			VM   struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"vm"`
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
		} `json:"nic"`
	}
	url := "https://ovirt-cl.zi-tel.com/ovirt-engine/api/vms/" + VMUUID + "/nics"
	method := "GET"

	payload := strings.NewReader(``)
	client := &http.Client{
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		//fmt.Println(err)
		return nil
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, err := client.Do(req)
	if err != nil {
		//fmt.Println(err)
		///TODO: ErrorHandling
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		//fmt.Println(err)
		///TODO: ErrorHandling
		return nil
	}
	_VMNIC := VMNIC{}
	err = json.Unmarshal(body, &_VMNIC)
	//fmt.Println("ListNIC: res", string(body))
	if err != nil {
		///TODO: ErrorHandling
		//fmt.Println(err)
		//return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice
	}
	_NICList := NICList{}
	_Data := _NICList.NIC
	x := struct {
		Mac             string `json:"mac"`
		IPv4            string `json:"IPv4"`
		IPv6            string `json:"IPv6"`
		ReportedDevices struct {
			Mac  string `json:"mac"`
			IPv4 string `json:"IPv4"`
			IPv6 string `json:"IPv6"`
		} `json:"reported_devices"`
	}{}
	for _, i := range _VMNIC.Nic {
		x.IPv4 = "1.1.1.1"
		///TODO:GetAssignedIP
		x.IPv6 = "Null"
		x.Mac = i.Mac.Address
		x.ReportedDevices.Mac = i.ReportedDevices.ReportedDevice[0].Mac.Address
		x.ReportedDevices.IPv4 = i.ReportedDevices.ReportedDevice[0].Ips.IP[0].Address
		x.ReportedDevices.IPv6 = i.ReportedDevices.ReportedDevice[0].Ips.IP[1].Address
		_Data = append(_Data, x)
	}
	_NICList.NIC = _Data
	return _NICList.NIC
}
func listDisks(VMUUID string, ba string) []struct {
	Name       string `json:"Name"`
	TotalSize  string `json:"TotalSize"`
	ActualSize string `json:"ActualSize"`
} {

	type DiskList struct {
		Disk []struct {
			Name       string `json:"Name"`
			TotalSize  string `json:"TotalSize"`
			ActualSize string `json:"ActualSize"`
		} `json:"Disk"`
	}
	type ListDisks struct {
		DiskAttachment []struct {
			Active              string `json:"active"`
			Bootable            string `json:"bootable"`
			Interface           string `json:"interface"`
			LogicalName         string `json:"logical_name"`
			PassDiscard         string `json:"pass_discard"`
			ReadOnly            string `json:"read_only"`
			UsesScsiReservation string `json:"uses_scsi_reservation"`
			Disk                struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"disk"`
			VM struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"vm"`
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"disk_attachment"`
	}
	url := "https://ovirt-cl.zi-tel.com/ovirt-engine/api/vms/" + VMUUID + "/diskattachments"
	method := "GET"

	payload := strings.NewReader(``)

	client := &http.Client{
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		//fmt.Println(err)
		return nil
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", ba)

	res, err := client.Do(req)
	if err != nil {
		//fmt.Println(err)
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	//fmt.Println("ListDisk: res", string(body))
	if err != nil {
		//fmt.Println(err)
		return nil
	}
	_ListDisks := ListDisks{}
	err = json.Unmarshal(body, &_ListDisks)
	if err != nil {
		//fmt.Println(err)
		return nil
	}

	_DiskList := DiskList{}
	for _, v := range _ListDisks.DiskAttachment {
		_DiskList.Disk = append(_DiskList.Disk, DiskDetails(v.Disk.ID, ba))

	}

	return _DiskList.Disk
}

func DiskDetails(id string, ba string) struct {
	Name       string `json:"Name"`
	TotalSize  string `json:"TotalSize"`
	ActualSize string `json:"ActualSize"`
} {
	type DiskDetail struct {
		ActualSize      string `json:"actual_size"`
		Alias           string `json:"alias"`
		Backup          string `json:"backup"`
		ContentType     string `json:"content_type"`
		Format          string `json:"format"`
		ImageID         string `json:"image_id"`
		PropagateErrors string `json:"propagate_errors"`
		ProvisionedSize string `json:"provisioned_size"`
		QcowVersion     string `json:"qcow_version"`
		Shareable       string `json:"shareable"`
		Sparse          string `json:"sparse"`
		Status          string `json:"status"`
		StorageType     string `json:"storage_type"`
		TotalSize       string `json:"total_size"`
		WipeAfterDelete string `json:"wipe_after_delete"`
		DiskProfile     struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"disk_profile"`
		Quota struct {
			Href string `json:"href"`
			ID   string `json:"id"`
		} `json:"quota"`
		StorageDomains struct {
			StorageDomain []struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"storage_domain"`
		} `json:"storage_domains"`
		Actions struct {
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
		} `json:"actions"`
		Name        string `json:"name"`
		Description string `json:"description"`
		Href        string `json:"href"`
		ID          string `json:"id"`
		Link        []struct {
			Href string `json:"href"`
			Rel  string `json:"rel"`
		} `json:"link"`
	}
	//fmt.Println("List Disk: ",id)
	url := "https://ovirt-cl.zi-tel.com/ovirt-engine/api/disks/" + id
	method := "GET"

	payload := strings.NewReader(``)

	client := &http.Client{
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		//fmt.Println(err)
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", ba)

	res, err := client.Do(req)
	if err != nil {
		//fmt.Println(err)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		//fmt.Println(err)
	}

	_DiskDetail := DiskDetail{}
	err = json.Unmarshal(body, &_DiskDetail)
	if err != nil {
		//fmt.Println(err)
	}

	Disk := struct {
		Name       string `json:"Name"`
		TotalSize  string `json:"TotalSize"`
		ActualSize string `json:"ActualSize"`
	}{
		Name:       _DiskDetail.Alias,
		TotalSize:  _DiskDetail.TotalSize,
		ActualSize: _DiskDetail.ActualSize,
	}

	return Disk
}
func (o ovirt) listTemplate(c echo.Context) error {
	type templateList struct {
		Template []struct {
			Status  string `json:"status"`
			Version struct {
				VersionName   string `json:"version_name"`
				VersionNumber string `json:"version_number"`
				BaseTemplate  struct {
					Href string `json:"href"`
					ID   string `json:"id"`
				} `json:"base_template"`
			} `json:"version"`
			Actions struct {
				Link []struct {
					Href string `json:"href"`
					Rel  string `json:"rel"`
				} `json:"link"`
			} `json:"actions"`
			Name        string `json:"name"`
			Description string `json:"description"`
			Comment     string `json:"comment"`
			Href        string `json:"href"`
			ID          string `json:"id"`
			Bios        struct {
				BootMenu struct {
					Enabled string `json:"enabled"`
				} `json:"boot_menu"`
				Type string `json:"type"`
			} `json:"bios"`
			CPU struct {
				Architecture string `json:"architecture"`
				Topology     struct {
					Cores   string `json:"cores"`
					Sockets string `json:"sockets"`
					Threads string `json:"threads"`
				} `json:"topology"`
			} `json:"cpu"`
			Display struct {
				AllowOverride       string `json:"allow_override"`
				CopyPasteEnabled    string `json:"copy_paste_enabled"`
				DisconnectAction    string `json:"disconnect_action"`
				FileTransferEnabled string `json:"file_transfer_enabled"`
				Monitors            string `json:"monitors"`
				SingleQxlPci        string `json:"single_qxl_pci"`
				SmartcardEnabled    string `json:"smartcard_enabled"`
				Type                string `json:"type"`
			} `json:"display"`
			Io struct {
				Threads string `json:"threads"`
			} `json:"io"`
			Memory    string `json:"memory"`
			Migration struct {
				AutoConverge string `json:"auto_converge"`
				Compressed   string `json:"compressed"`
				Encrypted    string `json:"encrypted"`
			} `json:"migration"`
			Origin string `json:"origin"`
			Os     struct {
				Boot struct {
					Devices struct {
						Device []string `json:"device"`
					} `json:"devices"`
				} `json:"boot"`
				Type string `json:"type"`
			} `json:"os"`
			Sso struct {
				Methods struct {
					Method []struct {
						ID string `json:"id"`
					} `json:"method"`
				} `json:"methods"`
			} `json:"sso"`
			Stateless string `json:"stateless"`
			Type      string `json:"type"`
			Usb       struct {
				Enabled string `json:"enabled"`
			} `json:"usb"`
			Link []struct {
				Href string `json:"href"`
				Rel  string `json:"rel"`
			} `json:"link"`
			CPUShares        string `json:"cpu_shares"`
			CreationTime     int64  `json:"creation_time"`
			DeleteProtected  string `json:"delete_protected"`
			HighAvailability struct {
				Enabled  string `json:"enabled"`
				Priority string `json:"priority"`
			} `json:"high_availability"`
			LargeIcon struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"large_icon"`
			MemoryPolicy struct {
				Guaranteed string `json:"guaranteed"`
				Max        string `json:"max"`
			} `json:"memory_policy"`
			MigrationDowntime  string `json:"migration_downtime"`
			MultiQueuesEnabled string `json:"multi_queues_enabled"`
			PlacementPolicy    struct {
				Affinity string `json:"affinity"`
			} `json:"placement_policy"`
			SmallIcon struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"small_icon"`
			StartPaused                 string `json:"start_paused"`
			StorageErrorResumeBehaviour string `json:"storage_error_resume_behaviour"`
			Cluster                     struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"cluster,omitempty"`
			TimeZone struct {
				Name string `json:"name"`
			} `json:"time_zone,omitempty"`
			CPUProfile struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"cpu_profile,omitempty"`
			Initialization struct {
				AuthorizedSSHKeys        string `json:"authorized_ssh_keys"`
				CloudInitNetworkProtocol string `json:"cloud_init_network_protocol"`
				CustomScript             string `json:"custom_script"`
				HostName                 string `json:"host_name"`
				NicConfigurations        struct {
				} `json:"nic_configurations"`
				RegenerateSSHKeys string `json:"regenerate_ssh_keys"`
				UserName          string `json:"user_name"`
			} `json:"initialization,omitempty"`
		} `json:"template"`
	}
	type templateListResponse struct {
		Data []struct {
			Name string `json:"name"`
		} `json:"Data"`
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	url := OvirtURL + "/ovirt-engine/api/templates?filter=true&search=Cloud"
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)

	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	_templateList := templateList{}
	err = json.Unmarshal(body, &_templateList)
	//fmt.Println("resp:",string(body))
	_templateListResponse := templateListResponse{
		Data:    nil,
		Message: "Done",
		Origin:  "ListTemplate",
		Code:    1000,
	}
	_Data := _templateListResponse.Data
	y := struct {
		Name string `json:"name"`
	}{}
	for _, v := range _templateList.Template {
		y.Name = v.Name
		_Data = append(_Data, y)
	}
	_templateListResponse.Data = _Data
	return c.JSON(http.StatusOK, _templateListResponse)
	//return c.String(http.StatusOK, string(b))
}

func (o ovirt) vmHistory(c echo.Context) error {

	type VMStatistics struct {
		Statistic []struct {
			Kind   string `json:"kind"`
			Type   string `json:"type"`
			Unit   string `json:"unit"`
			Values struct {
				Value []struct {
					Datum int64 `json:"datum"`
				} `json:"value"`
			} `json:"values"`
			VM struct {
				Href string `json:"href"`
				ID   string `json:"id"`
			} `json:"vm,omitempty"`
			Name        string `json:"name"`
			Description string `json:"description"`
			Href        string `json:"href,omitempty"`
			ID          string `json:"id"`
		} `json:"statistic"`
	}
	type VMStatisticsResponse struct {
		Data []struct {
			Kind   string `json:"kind"`
			Type   string `json:"type"`
			Unit   string `json:"unit"`
			Values struct {
				Value []struct {
					Datum int64 `json:"datum"`
				} `json:"value"`
			} `json:"values"`
			Name        string `json:"name"`
			Description string `json:"description"`
			//Href        string `json:"href,omitempty"`
			//ID          string `json:"id"`
		} `json:"statistic"`
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	vmuuid := c.FormValue("VmUUID")
	url := OvirtURL + "/ovirt-engine/api/vms/" + vmuuid + "/statistics"
	client := &http.Client{}
	req, err := http.NewRequest("GET", url, nil)

	if err != nil {
		fmt.Println(err)
	}
	req.Header.Add("Version", "4")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Authorization", BA)

	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	_VMStatistics := VMStatistics{}
	err = json.Unmarshal(body, &_VMStatistics)
	_VMStatisticsResponse := VMStatisticsResponse{
		Data:    nil,
		Message: "Done",
		Origin:  "vmHistory",
		Code:    1000,
	}
	_Data := _VMStatisticsResponse.Data
	y := struct {
		Kind   string `json:"kind"`
		Type   string `json:"type"`
		Unit   string `json:"unit"`
		Values struct {
			Value []struct {
				Datum int64 `json:"datum"`
			} `json:"value"`
		} `json:"values"`
		Name        string `json:"name"`
		Description string `json:"description"`
		//Href        string `json:"href,omitempty"`
		//ID          string `json:"id"`
	}{}
	for _, v := range _VMStatistics.Statistic {
		y.Kind = v.Kind
		y.Unit = v.Unit
		y.Type = v.Type
		y.Values = v.Values
		y.Name = v.Name
		y.Description = v.Description
		_Data = append(_Data, y)
	}
	_VMStatisticsResponse.Data = _Data
	return c.JSON(http.StatusOK, _VMStatisticsResponse)
}

func (o ovirt) SSHKeyGen(c echo.Context) error {
	type SSHKeyGenResponse struct {
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	email:=fmt.Sprintf("%s",claims["mail"])
	fmt.Println(email)

	mrand.Seed(time.Now().Unix())
	var output strings.Builder
	//Only lowercase
	charSet := "abcdedfghijklmnopqrstABCDEFGHIJKLMNOP0123456789"
	length := 20
	for i := 0; i < length; i++ {
		random := mrand.Intn(len(charSet))
		randomChar := charSet[random]
		output.WriteString(string(randomChar))
	}

	publicKeyBlock := &pem.Block{}
	{
		// generate key
		privatekey, err := rsa.GenerateKey(rand.Reader, 1024)
		if err != nil {
			fmt.Printf("Cannot generate RSA key\n")
			//os.Exit(1)
		}
		publickey := &privatekey.PublicKey

		// dump private key to file
		var privateKeyBytes []byte = x509.MarshalPKCS1PrivateKey(privatekey)
		privateKeyBlock := &pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: privateKeyBytes,
		}
		privatePem, err := os.Create("/tmp/" + output.String() + "-private.pem")
		if err != nil {
			fmt.Printf("error when create private.pem: %s \n", err)
			//os.Exit(1)
		}
		err = pem.Encode(privatePem, privateKeyBlock)
		if err != nil {
			fmt.Printf("error when encode private pem: %s \n", err)
			//os.Exit(1)
		}

		// dump public key to file
		publicKeyBytes, err := x509.MarshalPKIXPublicKey(publickey)
		if err != nil {
			fmt.Printf("error when dumping publickey: %s \n", err)
			//os.Exit(1)
		}
		publicKeyBlock = &pem.Block{
			Type:  "PUBLIC KEY",
			Bytes: publicKeyBytes,
		}
		publicPem, err := os.Create("/tmp/" + output.String() + "-public.pem")
		if err != nil {
			fmt.Printf("error when create public.pem: %s \n", err)
			//os.Exit(1)
		}

		err = pem.Encode(publicPem, publicKeyBlock)
		if err != nil {
			fmt.Printf("error when encode public pem: %s \n", err)
			//os.Exit(1)
		}
		sendMail("Generated SSH Key pairs is attached to this email", "ZiCloud KeyPair", "inbox@sassan.co", []string{"/tmp/" + output.String() + "-public.pem", "/tmp/" + output.String() + "-private.pem"})
	}
	_SSHKeyGenResponse := SSHKeyGenResponse{
		Message: string(pem.EncodeToMemory(publicKeyBlock)),
		Origin:  "SSHKeyGen",
		Code:    1000,
	}
	return c.JSON(http.StatusOK, _SSHKeyGenResponse)
}
