Package com.cybozu.vmbkp.profile

Source Code of com.cybozu.vmbkp.profile.ProfileGeneration

/**
* @file
* @brief ProfileGeneration
*
* Copyright (C) 2009,2010 Cybozu Inc., all rights reserved.
*
* @author Takashi HOSHINO <hoshino@labs.cybozu.co.jp>
*/
package com.cybozu.vmbkp.profile;

import java.util.Calendar;
import java.util.List;
import java.util.LinkedList;
import java.util.Set;
import java.util.TreeSet;
import java.util.Collections;
import java.util.logging.Logger;

import java.io.File;
import java.io.IOException;

import com.cybozu.vmbkp.config.Group;
import com.cybozu.vmbkp.config.Entry;
import com.cybozu.vmbkp.config.FormatString;
import com.cybozu.vmbkp.config.FormatInt;
import com.cybozu.vmbkp.config.FormatBool;
import com.cybozu.vmbkp.config.ParseException;
import com.cybozu.vmbkp.config.NotNormalFileException;

import com.cybozu.vmbkp.util.BackupMode;
import com.cybozu.vmbkp.util.VmInfo;
import com.cybozu.vmbkp.util.SnapInfo;
import com.cybozu.vmbkp.util.VmdkInfo;
import com.cybozu.vmbkp.util.AdapterType;
import com.cybozu.vmbkp.util.Utility;
import com.cybozu.vmbkp.profile.ConfigWrapper;

/**
* @brief Wrapper class to access vmbkp_generation.profile.
*/
public class ProfileGeneration
    extends ConfigWrapper
{
    public static final String FILE_NAME = "vmbkp_generation.profile";
   
    /**
     * Logger.
     */
    private static final Logger logger_ =
        Logger.getLogger(ProfileGeneration.class.getName());
   
    /**
     * Group [generation].
     */
    private Group generation_;

    /**
     * Default constructor. This will create an empty profile.
     */
    public ProfileGeneration()
    {
        super();
        initializeGroups();
    }
   
    /**
     * Read the specified config file and construct an object with it.
     *
     * @param filePath Path to a vmbkp_generation.profile file.
     */
    public ProfileGeneration(String filePath)
        throws IOException, ParseException, NotNormalFileException
    {
        super(filePath);
        initializeGroups();
    }

    /**
     * Initialize group(s).
     */
    private void initializeGroups()
    {
        /* initialize group(s) */
        generation_ = new Group("generation");
    }

    /**
     * Generate Group of [disk "`diskId`"]
     */
    private Group generateDiskGroup(int diskId)
    {
        return new Group("disk", Integer.toString(diskId));
    }

    /**
     * Generate Group of [index "disk"]
     */
    private Group generateDiskIndexGroup()
    {
        return new Group("index", "disk");
    }

    /**
     * Generate Groups of [index "controller"]
     */
    private Group generateControllerIndexGroup()
    {
        return new Group("index", "controller");
    }

    /**
     * Generate Group of [controller "`ckey`"]
     *
     * @param ckey key of the specified controller device.
     */
    private Group generateControllerGroup(int ckey)
    {
        return new Group("controller", Integer.toString(ckey));
    }
   
    /**
     * Initialize generation profile.
     *
     * @param genId genration id.
     * @param prevGenId previous generation id.
     *        that this generation depends on.
     * @param vmInfo virtual machine info.
     * @param snapInfo snapshot info.
     * @param vmdkInfoList list of vmdk info.
     * @param calendar for timestamp.
     * @param use gziped archives or not.
     */
    public void initializeGeneration
        (int genId, int prevGenId,
         VmInfo vmInfo, SnapInfo snapInfo,
         List<VmdkInfo> vmdkInfoList,
         Calendar calendar, boolean isGzip)
    {
        logger_.info("initializeGeneration() begin.");

        /* [generation] group */
        initializeGenerationGroup
            (genId, prevGenId, vmInfo, snapInfo,
             calendar, vmdkInfoList.size());

        int diskId = 0;
        for (VmdkInfo vmdkInfo : vmdkInfoList) {
            /* [disk `diskId`] group */
            initializeDiskGroup(diskId, vmdkInfo, isGzip);
            diskId ++;
        }

        logger_.info("initializeGeneration() end.");
    }

    /**
     * Initialize contents in [generation] group.
     *
     * @param genId genration id.
     * @param prevGenId previous generation id.
     *        that this generation depends on.
     * @param vmInfo virtual machine info.
     * @param snapInfo snapshot info.
     * @param calendar for timestamp.
     * @param numVmdk # of vmdk files with the virtual machine.
     */
    private void initializeGenerationGroup
        (int genId, int prevGenId,
         VmInfo vmInfo, SnapInfo snapInfo,
         Calendar calendar, int numVmdk)
    {
        String timestamp = calendar.getTime().toString();
        long timestampMs = calendar.getTimeInMillis();

        cfg_.put(generation_, "generation_id", Integer.toString(genId));
        cfg_.put(generation_, "moref", vmInfo.getMoref());
        cfg_.put(generation_, "name", vmInfo.getName());
        cfg_.put(generation_, "status", "initialized");
        cfg_.put(generation_, "snapshot_moref", snapInfo.getMoref());
        cfg_.put(generation_, "snapshot_name", snapInfo.getName());
        cfg_.put(generation_, "ovf_filename", snapInfo.getMoref() + ".ovf");
        cfg_.put(generation_, "timestamp", timestamp);
        cfg_.put(generation_, "timestamp_ms", Long.toString(timestampMs));
        cfg_.put(generation_, "prev_generation_id",
                 Integer.toString(prevGenId));
        cfg_.put(generation_, "num_disks", Integer.toString(numVmdk));
        cfg_.put(generation_, "num_vmdkdump_succeeded", "0");
        cfg_.put(generation_, "num_vmdkdump_failed", "0");
    }

    /**
     * Initialize contents in [disk `diskId`] group.
     *
     * @param diskId Disk identifier inside the generation only.
     * @param vmdkInfo vmdk info.
     * @param isGzip use gziped archives or not.
     */
    private void initializeDiskGroup
        (int diskId, VmdkInfo vmdkInfo, boolean isGzip)
    {

        String iStr = Integer.toString(diskId);
        Group diskGroup = generateDiskGroup(diskId);

        cfg_.put(diskGroup, "remote_path", vmdkInfo.name_);
        cfg_.put(diskGroup, "uuid", vmdkInfo.uuid_);
        cfg_.put(diskGroup, "capacity", Long.toString(vmdkInfo.capacityInKB_) + "K");

        if (vmdkInfo.changeId_ != null) {
            cfg_.put(diskGroup, "change_id", vmdkInfo.changeId_);
        } else {
            cfg_.put(diskGroup, "change_id", "*");
        }

        String gzipExt = ""; if (isGzip) { gzipExt = ".gz"; }
       
        cfg_.put(diskGroup, "adapter_type", vmdkInfo.type_.toString());
        cfg_.put(diskGroup, "controller_key", Integer.toString(vmdkInfo.ckey_));
        cfg_.put(diskGroup, "device_key", Integer.toString(vmdkInfo.key_));
        cfg_.put(diskGroup, "bus_number", Integer.toString(vmdkInfo.busNumber_));
        cfg_.put(diskGroup, "unit_number", Integer.toString(vmdkInfo.unitNumber_));
           
        cfg_.put(diskGroup, "backup_mode", "unknown"); /* must be set later. */
        cfg_.put(diskGroup, "disk_mode", vmdkInfo.diskMode_);
        cfg_.put(diskGroup, "rdiff_timestamp_ms", "-1");
        cfg_.put(diskGroup, "filename_dump", iStr + ".dump" + gzipExt);
        cfg_.put(diskGroup, "filename_digest", iStr + ".digest" + gzipExt);
        cfg_.put(diskGroup, "filename_rdiff", iStr + ".rdiff" + gzipExt);
        cfg_.put(diskGroup, "filename_bmp", iStr + ".bmp");
        cfg_.put(diskGroup, "is_deleted_previous_dump", "false");
        cfg_.put(diskGroup, "is_changed", "undefined"); /* must be set later. */

        cfg_.put(diskGroup, "dump_begin_timestamp_ms", "-1");
        cfg_.put(diskGroup, "dump_end_timestamp_ms", "-1");

        cfg_.put(diskGroup, "status", "failed");

        /* index (uuid -> diskId) */
        Group diskIndexGroup = this.generateDiskIndexGroup();
        cfg_.put(diskIndexGroup, vmdkInfo.uuid_, iStr);

        /* make controller group and entries. */
        Group controllerGroup = this.generateControllerGroup(vmdkInfo.ckey_);
        cfg_.put(controllerGroup, "adapter_type", vmdkInfo.type_.toString());
        cfg_.put(controllerGroup, "bus_number", Integer.toString(vmdkInfo.busNumber_));

        /* index (uuid -> controller_key) */
        Group controllerIndexGroup = this.generateControllerIndexGroup();
        cfg_.put(controllerIndexGroup, vmdkInfo.uuid_,
                 Integer.toString(vmdkInfo.ckey_));

    }

    /**
     * Get [generation] generation_id as int.
     */
    public int getGenerationId()
    {
        return cfg_.getValAsInt(generation_, "generation_id");
    }

    /**
     * Get [generation] generation_id.
     */
    public String getGenerationIdStr()
    {
        return cfg_.getVal(generation_, "generation_id");
    }

    /**
     * Get diskId with uuid using [index "disk"].
     *
     * @return diskId in success, or -1 in failure.
     */
    public int getDiskIdWithUuid(String uuid)
    {
        Group diskIndexGroup = this.generateDiskIndexGroup();
        String iStr = cfg_.getVal(diskIndexGroup, uuid);
        if (iStr == null || ! FormatInt.canBeInt(iStr)) {
            return -1;
        }

        return FormatInt.toInt(iStr);
    }

    /**
     * Set [generation] status.
     */
    private void setStatus(String status)
    {
        cfg_.put(generation_, "status", status);
    }

    /**
     * Get [generation] status.
     */
    protected String getStatus()
    {
        return cfg_.getVal(generation_, "status");
    }

    /**
     * Set succeeded flag.
     */
    public void setIsSucceeded(boolean isSucceeded)
    {
        setStatus(isSucceeded ? "succeeded" : "failed");
    }

    /**
     * Check the generation backup succeeded.
     */
    public boolean isSucceeded()
    {
        String ret = this.getStatus();
        return (ret != null && ret.equals("succeeded"));
    }
   
    /**
     * Get [generation] moref.
     * This returns moref of the virtual machine, not the snapshot.
     */
    public String getMoref()
    {
        return cfg_.getVal(generation_, "moref");
    }

    /**
     * Get [generation] snapshot_moref.
     */
    public String getSnapshotMoref()
    {
        return cfg_.getVal(generation_, "snapshot_moref");
    }

    /**
     * Get [generation] timestamp_ms.
     */
    public String getTimestampMs()
    {
        return cfg_.getVal(generation_, "timestamp_ms");
    }

    /**
     * Get [disk "`diskId`"] remote_path.
     */
    public String getRemoteDiskPath(int diskId)
    {
        return this.getDiskGroupValAsQString(diskId, "remote_path");
    }

    /**
     * Get filename of [generation] filename_dump.
     */
    public String getDumpOutFileName(int diskId)
    {
        return this.getDiskGroupValAsAutoString(diskId, "filename_dump");
    }

    /**
     * Set filename of [generation] filename_dump.
     */
    public void setDumpOutFileName(int diskId, String filename)
    {
        cfg_.put(generateDiskGroup(diskId), "filename_dump", filename);
    }

    /**
     * Get path of dump out.
     */
    public String getDumpOutPath(int diskId)
    {
        String filename = getDumpOutFileName(diskId);
        if (filename == null) { return null; }
        return getDirectory() + "/" + filename;
    }

    /**
     * @return True if the dump out file exists.
     */
    public boolean isDumpOutExist(int diskId)
    {
        String filepath = getDumpOutPath(diskId);
        logger_.info("path: " + filepath); /* debug */
        if (filepath == null) { return false; }
        return (new File(filepath)).isFile();
    }

    /**
     * Get filename of [disk "`diskId`"] filename_digest.
     */
    public String getDigestOutFileName(int diskId)
    {
        return this.getDiskGroupValAsAutoString(diskId, "filename_digest");
    }

    /**
     * Set filename of [generateion] filename_digest.
     */
    public void setDigestOutFileName(int diskId, String filename)
    {
        cfg_.put(generateDiskGroup(diskId), "filename_digest", filename);
    }

    /**
     * Get path of digest out.
     */
    public String getDigestOutPath(int diskId)
    {
        String filename =  getDigestOutFileName(diskId);
        if (filename == null) { return null; }
        return getDirectory() + "/" + filename;
    }

    /**
     * @return True if the digest out file exists.
     */
    public boolean isDigestOutExist(int diskId)
    {
        String filepath = getDigestOutPath(diskId);
        logger_.info("path: " + filepath); /* debug */
        if (filepath == null) { return false; }
        return (new File(filepath)).isFile();
    }

    /**
     * Get filename of [disk "`diskId`"] filename_rdiff.
     */
    public String getRdiffOutFileName(int diskId)
    {
        return this.getDiskGroupValAsAutoString(diskId, "filename_rdiff");
    }       

    /**
     * The rdiff of this generation is for the latest generation
     * that is not (backup_mode is "incr" and is_changed is "false").
     */
    public String getRdiffOutPath(int diskId)
    {
        String fname = this.getRdiffOutFileName(diskId);
        if (fname == null) { return null; }
        return this.getDirectory() + "/" + fname;
    }

    /**
     * @return true if the rdiff out file exists.
     */
    public boolean isRdiffOutExist(int diskId)
    {
        String filepath = getRdiffOutPath(diskId);
        if (filepath == null) { return false; }
        return (new File(filepath)).isFile();
    }

    /**
     * Get filename of [disk "`diskId`"] filename_bmp.
     */
    public String getBmpInFileName(int diskId)
    {
        return this.getDiskGroupValAsAutoString(diskId, "filename_bmp");
    }

    /**
     * Get filename of [disk "`diskId`"] filename_bmp and return full path.
     */
    public String getBmpInPath(int diskId)
    {
        String fname = this.getBmpInFileName(diskId);
        if (fname == null) { return null; }
        return this.getDirectory() + "/" + fname;
    }

    /**
     * Get [disk "`diskId`"] uuid.
     */
    public String getUuid(int diskId)
    {
        return this.getDiskGroupValAsAutoString(diskId, "uuid");
    }

    /**
     * Get [disk "`diskId`"] change_id.
     */
    public String getChangeId(int diskId)
    {
        return this.getDiskGroupValAsAutoString(diskId, "change_id");
    }

    /**
     * Get [disk "`diskId`"] key as a quated string.
     */
    private String getDiskGroupValAsQString(int diskId, String key)
    {
        String val = cfg_.getVal(generateDiskGroup(diskId), key);

        if (val != null) {
            return FormatString.toQuatedString(val);
        } else {
            return null;
        }
    }
   
    /**
     * Get [disk "`diskId`"] key as a string.
     */
    private String getDiskGroupValAsAutoString(int diskId, String key)
    {
        String val = cfg_.getVal(generateDiskGroup(diskId), key);

        if (val != null) {
            return FormatString.toStringAuto(val);
        } else {
            return null;
        }
    }

    /**
     * Get [disk "`diskId`"] capacity as long value.
     */
    public long getCapacity(int diskId)
    {
        return cfg_.getValAsLong(generateDiskGroup(diskId), "capacity");
    }

    /**
     * Get [disk "`diskId`"] controller_key as int value.
     */
    public int getControllerDeviceKey(int diskId)
    {
        return cfg_.getValAsInt(generateDiskGroup(diskId), "controller_key");
    }

    /**
     * Get [disk "`diskId`"] device_key as int value.
     */
    public int getDiskDeviceKey(int diskId)
    {
        return cfg_.getValAsInt(generateDiskGroup(diskId), "device_key");
    }

    /**
     * Get [disk "`diskId`"] unit_number as int value.
     */
    public int getUnitNumber(int diskId)
    {
        return cfg_.getValAsInt(generateDiskGroup(diskId), "unit_number");
    }

    /**
     * Get [disk "`diskId`"] disk_mode.
     */
    public String getDiskMode(int diskId)
    {
        return cfg_.getVal(generateDiskGroup(diskId), "disk_mode");
    }

    /**
     * @return True if the specified disk is independent disk.
     */
    public boolean isIndependentDisk(int diskId)
    {
        return "independent_persistent".equals(getDiskMode(diskId));
    }

    /**
     * Get [controller "`ckey`" bus_number as int value.
     */
    public int getBusNumber(int ckey)
    {
        return cfg_.getValAsInt(generateControllerGroup(ckey), "bus_number");
    }

    /**
     * The vmdk with the specified diskId has been backuped successfuly?
     *
     * @param diskId disk id in the config.
     * @return true if status entry is "succeeded", or false.
     */
    public boolean isVmdkdumpSucceeded(int diskId)
    {
        String val = getDiskGroupValAsAutoString(diskId, "status");
        if (val == null) { return false; }
        return val.equals("succeeded");
    }
   
    /**
     * Set [disk "`diskId`"] status
     * and count
     * [generation] num_vmdkdump_succeeded
     * or
     * [generation] num_vmdkdump_failed
     *
     * @param diskId Disk id managed in ProfileGeneration.
     * @param isSucceeded true in success, false in failure.
     */
    public void setVmdkdumpResult(int diskId, boolean isSucceeded)
    {
        String status = (isSucceeded ? "succeeded" : "failed");
        cfg_.put(generateDiskGroup(diskId), "status", status);

        if (isSucceeded) {
            incrementNumOfSucceededVmdkdump();
        } else {
            incrementNumOfFailedVmdkdump();
        }
    }

    /**
     * Set [disk "`diskId`"] backup_mode.
     */
    public void setBackupMode(int diskId, BackupMode mode)
    {
        cfg_.put(generateDiskGroup(diskId), "backup_mode", mode.toString());
    }

    /**
     * Get [disk "`diskId`"] backup_mode.
     */
    public BackupMode getBackupMode(int diskId)
    {
        return BackupMode.parse
            (cfg_.getVal(generateDiskGroup(diskId), "backup_mode"));
    }

    /**
     * Check the specified mode is the same with [disk "`diskId`"] bacukp_mode.
     */
    public boolean isBackupModeSame(int diskId, BackupMode mode)
    {
        BackupMode thisMode = this.getBackupMode(diskId);
        if (thisMode == null || mode == null) { return false; }
        return thisMode == mode;
    }

    /**
     * Get [disk "`diskId`"] adapter_type as AdapterType.
     */
    public AdapterType getAdapterType(int diskId)
    {
        String typeStr =
            cfg_.getVal(generateDiskGroup(diskId), "adapter_type");

        if (typeStr == null) {
            return AdapterType.UNKNOWN;
        } else {
            return AdapterType.parse(typeStr);
        }
    }

    /**
     * Set adapter type [disk "`diskId`"] adapter_type.
     */
    public void setAdapterType(int diskId, AdapterType type)
    {
        cfg_.put(generateDiskGroup(diskId), "adapter_type", type.toString());
    }

    /**
     * Set [disk "`diskId`"] is_deleted_previous_dump flag.
     */
    public void setDeletedPreviousDump(int diskId, boolean isDeleted)
    {
        String val = (isDeleted ? "true" : "false");
        cfg_.put(generateDiskGroup(diskId), "is_deleted_previous_dump", val);
    }


    /**
     * Set [disk "`diskId`"] is_changed flag.
     */
    public void setIsChanged(int diskId, boolean isChanged)
    {
        String val = (isChanged ? "true" : "false");
        cfg_.put(generateDiskGroup(diskId), "is_changed", val);
    }

    /**
     * Get [disk "`diskId`"] is_changed flag.
     *
     * @param diskId
     * @return True if is_changed is true, False if is_changed is false,
     *         null if others (error).
     *
     */
    public Boolean isChanged(int diskId)
    {
        String str =
            cfg_.getVal(generateDiskGroup(diskId), "is_changed");

        if (str != null && FormatBool.isBool(str)) {
            if (FormatBool.toBool(str)) {
                return new Boolean(true);
            } else {
                return new Boolean(false);
            }
        }
        /* error */
        return null;
    }

    /**
     * Get ovf path.
     * This do not check the file exists or not.
     */
    public String getOvfPath()
    {
        String ovfFileName = cfg_.getVal(generation_, "ovf_filename");
        if (ovfFileName == null) { return null; }
        return getDirectory() + "/" + ovfFileName;
    }

    /**
     * Get a list of information of all vmdk files.
     * (sorted by diskId).
     */
    public List<Integer> getDiskIdList()
    {
        List<Integer> ret = new LinkedList<Integer>();
       
        /* Traverse the index (uuid -> diskId) */
        Group diskIndexGroup = this.generateDiskIndexGroup();
        List<Entry> entryList = cfg_.getAllEntries(diskIndexGroup);
        for (Entry entry : entryList) {
            String uuid = entry.getKey();
            String diskIdStr = entry.getVal();

            assert FormatInt.canBeInt(diskIdStr);
            int diskId = FormatInt.toInt(diskIdStr);
            assert diskId >= 0;
            assert getDiskIdWithUuid(uuid) == diskId;

            /* Now we get an available diskId */
            ret.add(new Integer(diskId));
        }

        Collections.sort(ret);
        return ret;
    }

    /**
     * Get number of succceeded vmdk dump.
     * [generation] num_vmdkdump_succeeded.
     *
     * @return Number of succeeded vmdk dump, or -1 in errors.
     */
    public int getNumOfSucceededVmdkdump()
    {
        int ret = cfg_.getValAsInt(generation_, "num_vmdkdump_succeeded");
        if (ret < 0) {
            logger_.warning
                ("num_vmdkdump_succeeded is not set or not an integer.");
        }
        return ret;
    }

    /**
     * Get number of failed vmdk dump.
     * [generation] num_vmdkdump_failed.
     *
     * @return Number of failed vmdk dump, or -1 in errors.
     */
    public int getNumOfFailedVmdkdump()
    {
        int ret = cfg_.getValAsInt(generation_, "num_vmdkdump_failed");
        if (ret < 0) {
            logger_.warning
                ("num_vmdkdump_failed is not set or not an integer.");
        }
        return ret;
    }

    /**
     * Increment [generation] num_vmdkdump_succeeded.
     */
    public void incrementNumOfSucceededVmdkdump()
    {
        int count = getNumOfSucceededVmdkdump();
        count ++;
        cfg_.put(generation_, "num_vmdkdump_succeeded",
                 (new Integer(count)).toString());
    }

    /**
     * Increment [generation] num_vmdkdump_failed.
     */
    public void incrementNumOfFailedVmdkdump()
    {
        int count = getNumOfFailedVmdkdump();
        count ++;
        cfg_.put(generation_, "num_vmdkdump_failed",
                 (new Integer(count)).toString());
    }

    /**
     * Set current time of [disk `diskId`] dump_begin_timestamp_ms.
     */
    public void setDumpBeginTimestamp(int diskId)
    {
        Group diskGroup = this.generateDiskGroup(diskId);
        long timestampMs = Calendar.getInstance().getTimeInMillis();
        cfg_.put(diskGroup, "dump_begin_timestamp_ms",
                 Long.toString(timestampMs));
    }

    /**
     * Set current timestamp of [disk `diskId`] dump_end_timestamp_ms.
     */
    public void setDumpEndTimestamp(int diskId)
    {
        Group diskGroup = this.generateDiskGroup(diskId);
        long timestampMs = Calendar.getInstance().getTimeInMillis();
        cfg_.put(diskGroup, "dump_end_timestamp_ms",
                 Long.toString(timestampMs));
    }

    /**
     * Get elapsed time in milliseconds to dump disk `diskId`.
     */
    public long getDumpElapsedTimeMs(int diskId)
    {
        Group diskGroup = this.generateDiskGroup(diskId);
       
        String beginStr = cfg_.getVal(diskGroup, "dump_begin_timestamp_ms");
        String endStr = cfg_.getVal(diskGroup, "dump_end_timestamp_ms");
        if (beginStr == null || endStr == null) {
            logger_.warning("beginStr or endStr is is null.");
            return -1;
        }
        if (FormatInt.canBeLong(beginStr) == false &&
            FormatInt.canBeLong(endStr)   == false) {

            logger_.warning("beginStr or endStr is not long value.");
            return -1;
        }

        long beginMs = FormatInt.toLong(beginStr);
        long endMs = FormatInt.toLong(endStr);

        return endMs - beginMs;
    }
   
}
TOP

Related Classes of com.cybozu.vmbkp.profile.ProfileGeneration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.