|  | @@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
 | 
	
		
			
				|  |  |  import com.alibaba.fastjson.JSONObject;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.core.metadata.IPage;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 | 
	
		
			
				|  |  | +import com.github.zafarkhaja.semver.Version;
 | 
	
		
			
				|  |  |  import com.xunmei.common.core.domain.R;
 | 
	
		
			
				|  |  |  import com.xunmei.common.core.utils.DateUtils;
 | 
	
		
			
				|  |  |  import com.xunmei.common.core.utils.StringUtils;
 | 
	
	
		
			
				|  | @@ -24,9 +25,7 @@ import org.slf4j.Logger;
 | 
	
		
			
				|  |  |  import org.slf4j.LoggerFactory;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.transaction.annotation.Transactional;
 | 
	
		
			
				|  |  | -import org.springframework.web.bind.annotation.PostMapping;
 | 
	
		
			
				|  |  | -import org.springframework.web.bind.annotation.RequestMapping;
 | 
	
		
			
				|  |  | -import org.springframework.web.bind.annotation.RestController;
 | 
	
		
			
				|  |  | +import org.springframework.web.bind.annotation.*;
 | 
	
		
			
				|  |  |  import org.springframework.web.multipart.MultipartFile;
 | 
	
		
			
				|  |  |  import javax.servlet.http.HttpServletRequest;
 | 
	
		
			
				|  |  |  import javax.servlet.http.HttpServletResponse;
 | 
	
	
		
			
				|  | @@ -87,6 +86,87 @@ public class DataController extends BaseController{
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     * 主机管理--批量升级
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @PostMapping("/addHostBatch")
 | 
	
		
			
				|  |  | +    public AjaxResult addHostBatch(String zipId,@RequestParam("hostIds[]") String[] hostIds){
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            String msg = upgradeBatchInfoService.addHostUpgradeBatch(zipId, hostIds);
 | 
	
		
			
				|  |  | +            return AjaxResult.success(msg);
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("主机管理-批量升级出现异常:{}",e);
 | 
	
		
			
				|  |  | +            return AjaxResult.error("升级批次创建失败,"+e.getMessage());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 主机管理--批量升级-先获取已上传的升级包下拉框
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @RequestMapping("/getZipInfos")
 | 
	
		
			
				|  |  | +    public Message getZipInfos(){
 | 
	
		
			
				|  |  | +        List<ZipPackInfo> list = zipPackInfoService.getList();
 | 
	
		
			
				|  |  | +        Collections.sort(list, new Comparator<ZipPackInfo>() {
 | 
	
		
			
				|  |  | +            @Override
 | 
	
		
			
				|  |  | +            public int compare(ZipPackInfo o1, ZipPackInfo o2) {
 | 
	
		
			
				|  |  | +                String o1ZipVersion = o1.getZipVersion();
 | 
	
		
			
				|  |  | +                String o2ZipVersion = o2.getZipVersion();
 | 
	
		
			
				|  |  | +                Version oldVersion,newVersion;
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    oldVersion = Version.valueOf(o1ZipVersion);
 | 
	
		
			
				|  |  | +                } catch (Exception e) {
 | 
	
		
			
				|  |  | +                    oldVersion = Version.valueOf("1.0.0");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    newVersion = Version.valueOf(o2ZipVersion);
 | 
	
		
			
				|  |  | +                } catch (Exception e) {
 | 
	
		
			
				|  |  | +                    newVersion = Version.valueOf("1.0.0");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if (oldVersion.compareTo(newVersion) > 0){
 | 
	
		
			
				|  |  | +                    return -1;
 | 
	
		
			
				|  |  | +                } else if (oldVersion.compareTo(newVersion) < 0) {
 | 
	
		
			
				|  |  | +                    return 1;
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    return 0;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        JSONArray array = new JSONArray();
 | 
	
		
			
				|  |  | +        JSONObject json;
 | 
	
		
			
				|  |  | +        for (ZipPackInfo zipPackInfo : list) {
 | 
	
		
			
				|  |  | +            json = new JSONObject();
 | 
	
		
			
				|  |  | +            json.put("id",zipPackInfo.getId());
 | 
	
		
			
				|  |  | +            if (StringUtils.isEmpty(zipPackInfo.getHostTypeName())){
 | 
	
		
			
				|  |  | +                json.put("text",zipPackInfo.getZipVersion());
 | 
	
		
			
				|  |  | +            }else {
 | 
	
		
			
				|  |  | +                json.put("text",zipPackInfo.getZipVersion() + "-" + zipPackInfo.getHostTypeName());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            array.add(json);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return Message.success(null,array);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     *  主机管理--批量升级-先根据页面勾选的主机筛选出可升级的主机hostIds,返回给页面操作升级
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @PostMapping("/validateHostBatch")
 | 
	
		
			
				|  |  | +    public AjaxResult validateHostBatch(String upgradeZipId,@RequestParam("hostIds[]") String[] hostIds){
 | 
	
		
			
				|  |  | +        if(StringUtils.isEmpty(upgradeZipId)){
 | 
	
		
			
				|  |  | +            return AjaxResult.error("请选择升级包!");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if(hostIds == null || hostIds.length == 0){
 | 
	
		
			
				|  |  | +            return AjaxResult.error("请选择需要升级的主机!");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            Map<String, Object> data = upgradeBatchInfoService.validateHostBatch(upgradeZipId, hostIds);
 | 
	
		
			
				|  |  | +            return AjaxResult.success(data);
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("主机管理--批量升级-根据页面勾选的主机筛选出可升级的主机出现异常:{}",e);
 | 
	
		
			
				|  |  | +            return AjaxResult.error(e.getMessage());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  |       * 主机管理--重启服务(创建任务)
 | 
	
		
			
				|  |  |       * @param hostId
 | 
	
		
			
				|  |  |       **/
 | 
	
	
		
			
				|  | @@ -115,6 +195,23 @@ public class DataController extends BaseController{
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     * 主机管理--删除主机-先验证主机是否存在升级任务
 | 
	
		
			
				|  |  | +     * @param hostId
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @RequestMapping("/getUpgradeTaskByHostId")
 | 
	
		
			
				|  |  | +    @ResponseBody
 | 
	
		
			
				|  |  | +    public Message getUpgradeTaskByHostId(String hostId){
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            List<UpgradeTask> list = upgradeTaskService.getByHostId(hostId);
 | 
	
		
			
				|  |  | +            return Message.success("获取获取任务成功!",list);
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("主机管理--删除主机-查询主机当前的升级任务出现异常:{}",e);
 | 
	
		
			
				|  |  | +            return Message.error("获取任务失败,"+e.getMessage());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  |       * 主机管理--当前版本号下拉框
 | 
	
		
			
				|  |  |       **/
 | 
	
		
			
				|  |  |      @RequestMapping("/getZipInfos3")
 | 
	
	
		
			
				|  | @@ -140,6 +237,71 @@ public class DataController extends BaseController{
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     *  主机管理--导出
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @RequestMapping(value = "/hostInfoListExport")
 | 
	
		
			
				|  |  | +    public void hostInfoListExport(
 | 
	
		
			
				|  |  | +            HostInfoVo hostInfoVo,
 | 
	
		
			
				|  |  | +            HttpServletResponse response) throws Exception {
 | 
	
		
			
				|  |  | +        Page<HostInfo> page = new Page<>();
 | 
	
		
			
				|  |  | +        page.setSize(5000);
 | 
	
		
			
				|  |  | +        page.setCurrent(1);
 | 
	
		
			
				|  |  | +        IPage<HostInfoVo> result = hostInfoService.selectHostInfoPage(page, hostInfoVo);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        List<HostInfoVo> list = result.getRecords();
 | 
	
		
			
				|  |  | +        Label label = null;
 | 
	
		
			
				|  |  | +        WritableSheet sheet = null;
 | 
	
		
			
				|  |  | +        WritableWorkbook workBook = null;
 | 
	
		
			
				|  |  | +        WorkbookSettings settings = new WorkbookSettings();
 | 
	
		
			
				|  |  | +        settings.setWriteAccess(null);
 | 
	
		
			
				|  |  | +        ByteArrayOutputStream os = new ByteArrayOutputStream();
 | 
	
		
			
				|  |  | +        InputStream is = null;
 | 
	
		
			
				|  |  | +        OutputStream out = null;
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            workBook = Workbook.createWorkbook(os, settings);
 | 
	
		
			
				|  |  | +            sheet = workBook.createSheet("sheet1", 0);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(0, 30);//设置Excel的宽度
 | 
	
		
			
				|  |  | +            sheet.setColumnView(1, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(2, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(3, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(4, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(5, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(6, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(7, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(8, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(9, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(10, 30);
 | 
	
		
			
				|  |  | +            sheet.setColumnView(11, 30);
 | 
	
		
			
				|  |  | +            this.addHostInfoToLabel(label, sheet);//向Excel添加标题
 | 
	
		
			
				|  |  | +            this.addHostContentInfoToLabel(label, sheet, list);//向Excel添加表格数据
 | 
	
		
			
				|  |  | +            workBook.write();
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("主机管理excel导出处理数据出现异常:{}", e);
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            workBook.close();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            is = new ByteArrayInputStream(os.toByteArray());
 | 
	
		
			
				|  |  | +            out = response.getOutputStream();
 | 
	
		
			
				|  |  | +            // 设置输出文件信息
 | 
	
		
			
				|  |  | +            response.setContentType("application/octet-stream;charset=UTF-8");
 | 
	
		
			
				|  |  | +            response.addHeader("Content-Disposition", "attachment;filename=" + new String(("主机管理列表" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".xls").getBytes("gb2312"), "ISO8859-1"));
 | 
	
		
			
				|  |  | +            // 写文件流
 | 
	
		
			
				|  |  | +            byte[] buffer = new byte[6 * 1024];
 | 
	
		
			
				|  |  | +            int len = 0;
 | 
	
		
			
				|  |  | +            while ((len = is.read(buffer, 0, buffer.length)) != -1) {
 | 
	
		
			
				|  |  | +                out.write(buffer, 0, len);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } catch (IOException e) {
 | 
	
		
			
				|  |  | +            log.error("主机管理excel导出处理流出现异常:{}", e);
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            is.close();
 | 
	
		
			
				|  |  | +            out.close();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  |       * 升级包管理-列表
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      @PostMapping("/zipList")
 | 
	
	
		
			
				|  | @@ -310,6 +472,39 @@ public class DataController extends BaseController{
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     * 主机管理-列表导出(给Excel导出增加标题)
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private WritableSheet addHostInfoToLabel(Label label, WritableSheet sheet) throws RowsExceededException, WriteException {
 | 
	
		
			
				|  |  | +        WritableFont font1 = new WritableFont(WritableFont.ARIAL, 12, WritableFont.BOLD);
 | 
	
		
			
				|  |  | +        WritableCellFormat cellFormat1 = new WritableCellFormat(font1);
 | 
	
		
			
				|  |  | +        label = new Label(0, 0, "序号", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(1, 0, "所属机构", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(2, 0, "主机名称", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(3, 0, "主机IP", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(4, 0, "当前版本号", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(5, 0, "目标版本号", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(6, 0, "升级状态", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(7, 0, "服务状态", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(8, 0, "白令海状态", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(9, 0, "传输加密", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(10, 0, "白令海版本号", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        label = new Label(11, 0, "注册时间", cellFormat1);
 | 
	
		
			
				|  |  | +        sheet.addCell(label);
 | 
	
		
			
				|  |  | +        return sheet;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  |       * 升级状态查询-详情导出(给Excel导出增加标题)
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      private WritableSheet addBatchHostDetailToLabel(Label label, WritableSheet sheet) throws RowsExceededException, WriteException {
 | 
	
	
		
			
				|  | @@ -340,6 +535,53 @@ public class DataController extends BaseController{
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     * 主机管理-列表导出(往Excel中添加内容)
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private void addHostContentInfoToLabel(Label label, WritableSheet sheet, List<HostInfoVo> list) throws Exception {
 | 
	
		
			
				|  |  | +        WritableFont writableFont = new WritableFont(WritableFont.createFont("宋体"), 11, WritableFont.NO_BOLD, false);
 | 
	
		
			
				|  |  | +        WritableCellFormat writableCellFormat = new WritableCellFormat(writableFont);
 | 
	
		
			
				|  |  | +        writableCellFormat.setWrap(true);
 | 
	
		
			
				|  |  | +        for (int i = 0; i < list.size(); i++) {
 | 
	
		
			
				|  |  | +            HostInfoVo vdso = list.get(i);
 | 
	
		
			
				|  |  | +            label = new Label(0, i + 1, i + 1 + "", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(1, i + 1, StringUtils.isNotEmpty(vdso.getHostOrgName()) ? vdso.getHostOrgName() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(2, i + 1, StringUtils.isNotEmpty(vdso.getHostName()) ? vdso.getHostName() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(3, i + 1, StringUtils.isNotEmpty(vdso.getHostIp()) ? vdso.getHostIp() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(4, i + 1, StringUtils.isNotEmpty(vdso.getZipVersion()) ? vdso.getZipVersion() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(5, i + 1, StringUtils.isNotEmpty(vdso.getTargetVersion()) ? vdso.getTargetVersion() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            String updateStatusStr = "-";
 | 
	
		
			
				|  |  | +            if (vdso.getUpdateStatus() == null) {
 | 
	
		
			
				|  |  | +                updateStatusStr = "-";
 | 
	
		
			
				|  |  | +            } else if (vdso.getUpdateStatus() == 0) {
 | 
	
		
			
				|  |  | +                updateStatusStr = "进行中";
 | 
	
		
			
				|  |  | +            } else if (vdso.getUpdateStatus() == 1) {
 | 
	
		
			
				|  |  | +                updateStatusStr = "成功";
 | 
	
		
			
				|  |  | +            } else if (vdso.getUpdateStatus() == 2) {
 | 
	
		
			
				|  |  | +                updateStatusStr = "失败";
 | 
	
		
			
				|  |  | +            } else if (vdso.getUpdateStatus() == 3) {
 | 
	
		
			
				|  |  | +                updateStatusStr = "重试中";
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            label = new Label(6, i + 1, updateStatusStr, writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(7, i + 1, vdso.getServerStatus() == 1 ? "正常" : "异常", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(8, i + 1, vdso.getHostStatus() == 1 ? "在线" : "离线", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(9, i + 1, vdso.getEncryption() == 1 ? "是" : "否", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(10, i + 1, StringUtils.isNotEmpty(vdso.getAgentVersion()) ? vdso.getAgentVersion() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +            label = new Label(11, i + 1, StringUtils.isNotEmpty(vdso.getRegisterDateTime()) ? vdso.getRegisterDateTime() : "-", writableCellFormat);
 | 
	
		
			
				|  |  | +            sheet.addCell(label);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  |       * 升级状态查询-详情导出(往Excel中添加内容)
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      private void addBatchHostContentToLabel(Label label, WritableSheet sheet, List<BatchHostInfo> list) throws Exception {
 |