public function createAction()
 {
     $node_id = $this->getRequest("node_id", "");
     $idc = $this->getRequest("idc", "");
     $op_user = $this->userInfo["userName"];
     // 1. parameter null
     if ($node_id === "" || $idc === "") {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_BAD_ARGS);
         QconfMgrLog::err(__FILE__, __LINE__, "paramter: 'path', 'main_buss_id' or 'idc' are required!");
         echo json_encode($res);
         return;
     }
     // 2. node is exist
     $node = NodeServ::getNode($node_id);
     if ($node === FALSE) {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_NODE_NOT_EXIST);
         QconfMgrLog::err(__FILE__, __LINE__, "node of node_id({$node_id}) not exist!");
         echo json_encode($res);
         return;
     }
     // 3. node level is smaller than 2
     $node_level = $node["node_level"];
     if ($node_level < 2) {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_SNAPSHOT_NODE_LEVEL_ERROR);
         QconfMgrLog::err(__FILE__, __LINE__, "snapshot mustn't be created on root node!");
         echo json_encode($res);
         return;
     }
     // 4. already exist snapshot
     $node_whole = $node["node_whole"];
     //[USERPERM CHECK]
     $userperm_ret = UserPermServ::checkPerm($op_user, $node_whole);
     if ($userperm_ret === FALSE) {
         QconfMgrLog::err(__FILE__, __LINE__, "Insufficient permission of {$op_user} on node {$node_whole}");
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_USER_PERM_PERMISSION_DENIED);
         echo json_encode($res);
         return;
     }
     $main_buss_id = $node["main_buss_id"];
     $existed = SnapShotUtil::existSnapShotForSnapShot($main_buss_id, $node_whole, $snapshot_path);
     if ($existed === FALSE) {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_SNAPSHOT_MODULE_FAILED);
         QconfMgrLog::err(__FILE__, __LINE__, "check snapshot existed failed");
         echo json_encode($res);
         return;
     }
     if ($existed === InfoDescUtil::SNAPSHOT_FILE_EXIST) {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_SNAPSHOT_FILE_EXIST);
         $res["errmsg"] .= ": {$snapshot_path}";
         QconfMgrLog::err(__FILE__, __LINE__, "snapshot has already exist, snapshot_path({$snapshot_path})");
         echo json_encode($res);
         return;
     }
     // 5. idc validation
     $cur_idcs = $node["idc"];
     $check_res = self::idcValidation($idc, $cur_idcs);
     if ($check_res["errno"] != "0") {
         echo json_encode($check_res);
         return;
     }
     // 6. construct values
     $zk_web = new QconfZkWebBase(Log::INFO);
     $idc_list = preg_split("/[,]+/", trim($idc, ","));
     $descendant = NodeServ::getDescendant($node_whole);
     $descendant[] = $node;
     $idc_values = array();
     foreach ($idc_list as $idc_each) {
         $values_conf = array();
         $values_serv = array();
         $idc_host = ZkConf::getZkHost($idc_each);
         $zk_web->connect($idc_host);
         foreach ($descendant as $one_descendant) {
             $desc_node_whole = $one_descendant["node_whole"];
             $desc_node_type_code = $one_descendant["node_type_code"];
             $desc_node_idcs = $one_descendant["idc"];
             $exist_idc = in_array($idc_each, explode(',', $desc_node_idcs));
             if ($exist_idc === FALSE) {
                 continue;
             }
             if ($desc_node_type_code === InfoDescUtil::NODE_TYPE_SERV_FATHER) {
                 // get services
                 $get_ret = ServiceController::getServicesAndStatusWithLink($zk_web, $desc_node_whole, $idc_each, $services);
                 if ($get_ret != InfoDescUtil::QCONF_OK) {
                     $res = InfoDescUtil::getErrorMsg($get_ret);
                     $res["data"] .= $idc_each;
                     echo json_encode($res);
                     return;
                 }
                 $values_serv[$desc_node_whole] = $services;
             }
             // get conf
             $get_conf = NodeController::getConfWithLink($zk_web, $desc_node_whole, $idc_each, $node_val);
             if ($get_conf != InfoDescUtil::QCONF_OK) {
                 $res = InfoDescUtil::getErrorMsg($get_conf);
                 $res["data"] .= $idc_each;
                 echo json_encode($res);
                 return;
             }
             $values_conf[$desc_node_whole] = $node_val;
         }
         $values = array();
         $values["conf"] = $values_conf;
         $values["serv"] = $values_serv;
         $idc_values[$idc_each] = $values;
     }
     // 7. create snapshot
     $main_buss_id = $node["main_buss_id"];
     $sub_buss_id = $node["sub_buss_id"];
     $create_res = SnapShotUtil::createSnapShot($main_buss_id, $node_whole, $op_user, $idc_values);
     if ($create_res === FALSE) {
         $res = InfoDescUtil::getErrorMsg(InfoDescUtil::ERR_SNAPSHOT_MODULE_FAILED);
         QconfMgrLog::err(__FILE__, __LINE__, "snapshot has already exist");
         echo json_encode($res);
         return;
     }
     OpServ::insert(InfoDescUtil::OP_TYPE_SNAPSHOT_ADD, $node_whole, $idc, InfoDescUtil::OP_STATUS_SUCCESS, $main_buss_id, $sub_buss_id, $op_user, "");
     // 8. return the right info
     $res = array("errno" => "0", "errmsg" => "", "data" => "create snapshot success!");
     $json = json_encode($res);
     echo $json;
 }