/*
* Scale Control Service
* File: ScaleControlService
* Version: 1.0.0
* Date: 2011-06-09
* Copyright 2011 ISCAS. All Rights Reserved
*/

package com.appspace.zmaster.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;
import org.internetware.icloud.portal.background.TestBed;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import com.appspace.common.service.LocalService;
import com.appspace.common.service.impl.LifecycleException;
import com.appspace.zmaster.fabric.PlatformFabric;

/*
* @author Hai He(hehai09@otcaix.iscas.cn)
*/
public class ScaleControlService extends LocalService{
private TestBed testbed;
private PlatformFabric platform;

private static Logger LOG = Logger.getLogger(ScaleControlService.class);

private int idleVM;
private int totalVM;
private ArrayList<String> idleList;

final int MIN_VM_NUMBER = 3;
final int VM_OP_INTERVAL = 10000;

@Override
public String getName() {
return "Scale Control Service";
}

@Override
public String getServiceId() {
return "scale_control_service";
}

@Override
public void init() throws LifecycleException {
super.init();
testbed
= new TestBed();
platform
= PlatformFabric.getInstance();
LOG.info(
"Success to Initialize Service --- " + getName());
}

@Override
public void start() throws LifecycleException {
ScaleThread sc
= new ScaleThread("Scale Thread");
sc.start();
LOG.info(
"STOP Success to Start Service --- " + getName());
}

class ScaleThread extends Thread {
public ScaleThread(String name) {
super(name);
}

public void run() {
while (true) {
checkStatus();
String label
= null;
LOG.info(
"idle vm number is " + idleVM);
if (idleVM < MIN_VM_NUMBER && idleVM != -1) {
int upNum = MIN_VM_NUMBER - idleVM;
String imgList
= testbed.GetCustomizedImgList("28");
JSONParser parser
= new JSONParser();
try {
JSONArray array
= (JSONArray) parser.parse(imgList);
Iterator iter
= array.iterator();
LOG.info(
"total up number is " + upNum);
while (iter.hasNext()) {
JSONObject obj
= (JSONObject) parser.parse((String) iter.next());
String id
= obj.get("id").toString();
String ip
= obj.get("ip").toString();
String status
= obj.get("status").toString();
String tpl
= obj.get("tpl").toString();
/* String name = obj.get("name").toString();
String nodeIp = obj.get("nodeIp").toString();
String gnome = obj.get("gnome").toString();
String customized = obj.get("customized").toString();
String mem = obj.get("mem").toString();
String cpu = obj.get("cpu").toString();
String disk = obj.get("disk").toString();
String info = obj.get("info").toString();
*/

if (upNum == 0) {
break;
}

if (status.equals("0") && tpl.equals("appspace")) {
String result
= testbed.BootImg("28", id);
if (result.equals("Successful")) {
upNum
--;
LOG.info(
"start a vm that already exist, ip is " + ip);
}
}

/*testbed.BootImg("28", id);
testbed.ShutdownImg("28", id);
testbed.Customize("28", "7", "appspace", "2", "512", "256", "1", "0");
*/
}
}
catch (Exception e) {
e.printStackTrace();
}
LOG.info(
"new vm number is " + upNum);
for (int j = 0; j < upNum; j++) {
try {
label
= testbed.Customize("28", "7", "test", "2", "128", "256", "1", "0");
}
catch (Exception e) {
e.printStackTrace();
}
LOG.info(
"start a new vm, ip is " + label);
}

upNum
= MIN_VM_NUMBER - idleVM;
int wait = 0;
int expect = totalVM + upNum;
while (wait < 2) {
try {
Thread.sleep(VM_OP_INTERVAL);
}
catch (InterruptedException e) {
LOG.info(
"time exception");
}
wait
++;
String[] servers
= platform.findServerNames();
LOG.info(
"scale up checking, now " + servers.length + " expect " + expect);
if (servers.length == expect) {
LOG.info(
"total vm number is " + servers.length);
break;
}
}

}
else if (idleVM > MIN_VM_NUMBER && idleVM != -1) {
int downNum = idleVM - MIN_VM_NUMBER;
LOG.info(
"downNum = " + downNum);
int i = 0;
while (i < downNum) {
int index = idleList.size() - 1;
String toShut
= idleList.get(index);
idleList.remove(index);
try {
String result
= testbed.ShutdownImg("28", toShut);
if (result.equals("Successful")) {
i
++;
}
}
catch (Exception e) {
e.printStackTrace();
}
LOG.info(
"close a vm, ip is " + toShut);
}

int wait = 0;
int expect = totalVM - downNum;
while (wait < 2) {
LOG.info(
"scale down checking ...");
try {
Thread.sleep(VM_OP_INTERVAL);
}
catch (InterruptedException e) {
LOG.info(
"time exception");
}
wait
++;
String[] servers
= platform.findServerNames();
LOG.info(
"scale down checking, now " + servers.length + " expect " + expect);
if (servers.length == totalVM - downNum) {
LOG.info(
"total vm number is " + servers.length);
break;
}
}
}
}
}
}

@Override
public void dispose() {
}

private void checkStatus() {
try {
Thread.sleep(VM_OP_INTERVAL
+ 5000);
}
catch (InterruptedException e) {
LOG.info(
"time exception");
}
String[] servers
= platform.findServerNames();
int len = servers.length;
if (len == 0) {
idleVM
= -1;
return;
}
else {
idleVM
= 0;
}
totalVM
= 0;
idleList
= new ArrayList<String>();
for (int i = 0; i < servers.length; i++) {
String name
= servers[i];
int size = platform.getServiceSize(name);
if (size == 0) {
idleVM
++;
idleList.add(name);
}
totalVM
++;
}
}

@Override
public Map<String, Object> getManagedMBeans() {
return null;
}
}