blob: 7e84b874aadf3478ee185b2adb2787c477d38ef6 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.hypervisor.vmware.mo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Properties;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class SnapshotDescriptor {
protected Logger logger = LogManager.getLogger(getClass());
private final Properties _properties = new Properties();
public SnapshotDescriptor() {
}
public void parse(byte[] vmsdFileContent) throws IOException {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(vmsdFileContent),"UTF-8"));
String line;
while ((line = in.readLine()) != null) {
// TODO, remember to remove this log, temporarily added for debugging purpose
logger.info("Parse snapshot file content: " + line);
String[] tokens = line.split("=");
if (tokens.length == 2) {
String name = tokens[0].trim();
String value = tokens[1].trim();
if (value.charAt(0) == '\"')
value = value.substring(1, value.length() - 1);
_properties.put(name, value);
}
}
} finally {
if (in != null)
in.close();
}
}
public void removeDiskReferenceFromSnapshot(String diskFileName) {
String numSnapshotsStr = _properties.getProperty("snapshot.numSnapshots");
if (numSnapshotsStr != null) {
int numSnaphosts = Integer.parseInt(numSnapshotsStr);
for (int i = 0; i < numSnaphosts; i++) {
String numDisksStr = _properties.getProperty(String.format("snapshot%d.numDisks", i));
int numDisks = Integer.parseInt(numDisksStr);
boolean diskFound = false;
for (int j = 0; j < numDisks; j++) {
String keyName = String.format("snapshot%d.disk%d.fileName", i, j);
String fileName = _properties.getProperty(keyName);
if (!diskFound) {
if (fileName.equalsIgnoreCase(diskFileName)) {
diskFound = true;
_properties.remove(keyName);
}
} else {
_properties.setProperty(String.format("snapshot%d.disk%d.fileName", i, j - 1), fileName);
}
}
if (diskFound)
_properties.setProperty(String.format("snapshot%d.numDisks", i), String.valueOf(numDisks - 1));
}
}
}
public byte[] getVmsdContent() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(bos, "UTF-8"));) {
out.write(".encoding = \"UTF-8\"");
out.newLine();
out.write(String.format("snapshot.lastUID = \"%s\"", _properties.getProperty("snapshot.lastUID")));
out.newLine();
String numSnapshotsStr = _properties.getProperty("snapshot.numSnapshots");
if (numSnapshotsStr == null || numSnapshotsStr.isEmpty())
numSnapshotsStr = "0";
out.write(String.format("snapshot.numSnapshots = \"%s\"", numSnapshotsStr));
out.newLine();
String value = _properties.getProperty("snapshot.current");
if (value != null) {
out.write(String.format("snapshot.current = \"%s\"", value));
out.newLine();
}
String key;
for (int i = 0; i < Integer.parseInt(numSnapshotsStr); i++) {
key = String.format("snapshot%d.uid", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.filename", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.displayName", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.description", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.createTimeHigh", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.createTimeLow", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.numDisks", i);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
int numDisks = Integer.parseInt(value);
for (int j = 0; j < numDisks; j++) {
key = String.format("snapshot%d.disk%d.fileName", i, j);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
key = String.format("snapshot%d.disk%d.node", i, j);
value = _properties.getProperty(key);
out.write(String.format("%s = \"%s\"", key, value));
out.newLine();
}
}
} catch (IOException e) {
assert (false);
logger.error("Unexpected exception ", e);
}
return bos.toByteArray();
}
private int getSnapshotId(String seqStr) {
if (seqStr != null) {
int seq = Integer.parseInt(seqStr);
String numSnapshotStr = _properties.getProperty("snapshot.numSnapshots");
assert (numSnapshotStr != null);
for (int i = 0; i < Integer.parseInt(numSnapshotStr); i++) {
String value = _properties.getProperty(String.format("snapshot%d.uid", i));
if (value != null && Integer.parseInt(value) == seq)
return i;
}
}
return 0;
}
public SnapshotInfo[] getCurrentDiskChain() {
ArrayList<SnapshotInfo> l = new ArrayList<SnapshotInfo>();
String current = _properties.getProperty("snapshot.current");
int id;
while (current != null) {
id = getSnapshotId(current);
String numDisksStr = _properties.getProperty(String.format("snapshot%d.numDisks", id));
int numDisks = 0;
if (numDisksStr != null && !numDisksStr.isEmpty()) {
numDisks = Integer.parseInt(numDisksStr);
DiskInfo[] disks = new DiskInfo[numDisks];
for (int i = 0; i < numDisks; i++) {
disks[i] =
new DiskInfo(_properties.getProperty(String.format("snapshot%d.disk%d.fileName", id, i)), _properties.getProperty(String.format(
"snapshot%d.disk%d.node", id, i)));
}
SnapshotInfo info = new SnapshotInfo();
info.setId(id);
info.setNumOfDisks(numDisks);
info.setDisks(disks);
info.setDisplayName(_properties.getProperty(String.format("snapshot%d.displayName", id)));
l.add(info);
}
current = _properties.getProperty(String.format("snapshot%d.parent", id));
}
return l.toArray(new SnapshotInfo[0]);
}
public static class SnapshotInfo {
private int _id;
private String _displayName;
private int _numOfDisks;
private DiskInfo[] _disks;
public SnapshotInfo() {
}
public void setId(int id) {
_id = id;
}
public int getId() {
return _id;
}
public void setDisplayName(String name) {
_displayName = name;
}
public String getDisplayName() {
return _displayName;
}
public void setNumOfDisks(int numOfDisks) {
_numOfDisks = numOfDisks;
}
public int getNumOfDisks() {
return _numOfDisks;
}
public void setDisks(DiskInfo[] disks) {
_disks = disks;
}
public DiskInfo[] getDisks() {
return _disks;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("SnapshotInfo : { id: ");
sb.append(_id);
sb.append(", displayName: ").append(_displayName);
sb.append(", numOfDisks: ").append(_numOfDisks);
sb.append(", disks: [");
if (_disks != null) {
int i = 0;
for (DiskInfo diskInfo : _disks) {
if (i > 0)
sb.append(", ");
sb.append(diskInfo.toString());
i++;
}
}
sb.append("]}");
return sb.toString();
}
}
public static class DiskInfo {
private final String _diskFileName;
private final String _deviceName;
public DiskInfo(String diskFileName, String deviceName) {
_diskFileName = diskFileName;
_deviceName = deviceName;
}
public String getDiskFileName() {
return _diskFileName;
}
public String getDeviceName() {
return _deviceName;
}
@Override
public String toString() {
return "DiskInfo: { device: " + _deviceName + ", file: " + _diskFileName + " }";
}
}
}