CLOUDSTACK-5779: Update vmdata command in Vmware

To use Gson rather than copy a file to it, follow the same as Xen and KVM.
This commit is contained in:
Sheng Yang 2014-01-21 11:43:50 -08:00
parent b79f949e1b
commit 1767ddac77
3 changed files with 12 additions and 305 deletions

View File

@ -296,6 +296,7 @@ import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
@ -2346,55 +2347,29 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.info("Executing resource VmDataCommand: " + _gson.toJson(cmd));
}
String routerPrivateIpAddress = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
String controlIp = getRouterSshControlIp(cmd);
Map<String, List<String[]>> data = new HashMap<String, List<String[]>>();
data.put(cmd.getVmIpAddress(), cmd.getVmData());
String vmIpAddress = cmd.getVmIpAddress();
List<String[]> vmData = cmd.getVmData();
String[] vmDataArgs = new String[vmData.size() * 2 + 4];
vmDataArgs[0] = "routerIP";
vmDataArgs[1] = routerPrivateIpAddress;
vmDataArgs[2] = "vmIP";
vmDataArgs[3] = vmIpAddress;
int i = 4;
for (String[] vmDataEntry : vmData) {
String folder = vmDataEntry[0];
String file = vmDataEntry[1];
String contents = (vmDataEntry[2] != null) ? vmDataEntry[2] : "none";
String json = new Gson().toJson(data);
s_logger.debug("VM data JSON IS:" + json);
vmDataArgs[i] = folder + "," + file;
vmDataArgs[i + 1] = contents;
i += 2;
}
json = Base64.encodeBase64String(json.getBytes());
String content = encodeDataArgs(vmDataArgs);
String tmpFileName = UUID.randomUUID().toString();
String args = "-d " + json;
if (s_logger.isDebugEnabled()) {
s_logger.debug("Run vm_data command on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", data: " + content);
}
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
try {
VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
SshHelper.scpTo(controlIp, DefaultDomRSshPort, "root", mgr.getSystemVMKeyFile(), null, "/tmp", content.getBytes(), tmpFileName, null);
try {
Pair<Boolean, String> result =
SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", mgr.getSystemVMKeyFile(), null, "/root/userdata.py " + tmpFileName);
if (!result.first()) {
s_logger.error("vm_data command on domain router " + controlIp + " failed. messge: " + result.second());
return new Answer(cmd, false, "VmDataCommand failed due to " + result.second());
}
} finally {
SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", mgr.getSystemVMKeyFile(), null, "rm /tmp/" + tmpFileName);
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", mgr.getSystemVMKeyFile(), null, "/opt/cloud/bin/vmdata.py " + args);
if (!result.first()) {
s_logger.error("vm_data command on domain router " + controlIp + " failed. messge: " + result.second());
return new Answer(cmd, false, "VmDataCommand failed due to " + result.second());
}
if (s_logger.isInfoEnabled()) {
s_logger.info("vm_data command on domain router " + controlIp + " completed");
}
} catch (Throwable e) {
String msg = "VmDataCommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg, e);
@ -2403,17 +2378,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return new Answer(cmd);
}
private String encodeDataArgs(String[] dataArgs) {
StringBuilder sb = new StringBuilder();
for (String arg : dataArgs) {
sb.append(arg);
sb.append("\n");
}
return sb.toString();
}
protected CheckSshAnswer execute(CheckSshCommand cmd) {
String vmName = cmd.getName();
String privateIp = cmd.getIp();

View File

@ -1,92 +0,0 @@
#!/usr/bin/python
# 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.
import sys
import base64
import string
import os
import tempfile
from subprocess import call
def vm_data(args):
router_ip = args.pop('routerIP')
vm_ip = args.pop('vmIP')
for pair in args:
pairList = pair.split(',')
vmDataFolder = pairList[0]
vmDataFile = pairList[1]
vmDataValue = args[pair]
cmd = ["/bin/bash", "/root/userdata.sh", "-v", vm_ip, "-F", vmDataFolder, "-f", vmDataFile]
fd = None
tmp_path = None
try:
fd,tmp_path = tempfile.mkstemp()
tmpfile = open(tmp_path, 'w')
if (vmDataFolder == "userdata" and vmDataValue != "none"):
vmDataValue = base64.urlsafe_b64decode(vmDataValue)
if vmDataValue != "none":
tmpfile.write(vmDataValue)
tmpfile.close()
cmd.append("-d")
cmd.append(tmp_path)
except:
if fd !=None:
os.close(fd)
os.remove(tmp_path)
return ''
try:
call(cmd)
txt = 'success'
except:
txt = ''
if (fd != None):
os.close(fd)
os.remove(tmp_path)
return txt
def parseFileData(fileName):
args = {}
fd = open(fileName)
line = fd.readline()
while (line != ""):
key=string.strip(line[:], '\n')
if (key == ""):
break
line=fd.readline()
val=string.strip(line[:], '\n')
args[key]=val
line=fd.readline()
return args
if __name__ == "__main__":
vm_data(parseFileData("/tmp/" + sys.argv[1]))

View File

@ -1,165 +0,0 @@
#!/bin/bash
# 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.
source /root/func.sh
lock="biglock"
#default timeout value is 30 mins as userdata command is not synchronized on agent side any more,
#and multiple commands can be sent to the same VR at a time
locked=$(getLockFile $lock 1800)
if [ "$locked" != "1" ]
then
exit 1
fi
usage() {
printf "Usage: %s: -v <vm ip> -F <vm data folder> -f <vm data file> -d <data to put in file> \n" $(basename $0) >&2
unlock_exit 2 $lock $locked
}
set -x
PORT=3922
create_htaccess() {
local vmIp=$1
local folder=$2
local file=$3
local result=0
entry="RewriteRule ^$file$ ../$folder/%{REMOTE_ADDR}/$file [L,NC,QSA]"
htaccessFolder="/var/www/html/latest"
htaccessFile=$htaccessFolder/.htaccess
mkdir -p $htaccessFolder
touch $htaccessFile
# Fixed the issue with checking if record exists, rewrote the else/if logic, reference issue CLOUDSTACK-2053
if ! grep -Fq "$entry" $htaccessFile
then
echo -e $entry >> $htaccessFile;
result=$?
fi
entry="Options -Indexes\\nOrder Deny,Allow\\nDeny from all\\nAllow from $vmIp"
testentry="Allow from $vmIp"
htaccessFolder="/var/www/html/$folder/$vmIp"
htaccessFile=$htaccessFolder/.htaccess
if ! grep -Fq "$testentry" $htaccessFile
then
mkdir -p $htaccessFolder
echo -e $entry > $htaccessFile
result=$?
fi
# Please reference issue CLOUDSTACK-2053, added to fix boto/cloud-init integration
htaccessFileNoIP="/var/www/html/latest/.htaccess"
metadataentry1='RewriteRule ^meta-data/$ ../metadata/%{REMOTE_ADDR}/meta-data [L,NC,QSA]'
metadataentry2='RewriteRule ^meta-data/(.*)$ ../metadata/%{REMOTE_ADDR}/$1 [L,NC,QSA]'
if ! grep -Fq "$metadataentry1" $htaccessFileNoIP
then
echo -e "$metadataentry1" >> $htaccessFileNoIP;
fi
if ! grep -Fq "$metadataentry2" $htaccessFileNoIP
then
echo -e "$metadataentry2" >> $htaccessFileNoIP;
fi
return $result
}
copy_vm_data_file() {
local vmIp=$1
local folder=$2
local file=$3
local dataFile=$4
dest=/var/www/html/$folder/$vmIp/$file
metamanifest=/var/www/html/$folder/$vmIp/meta-data
chmod +r $dataFile
cp $dataFile $dest
chmod 644 $dest
touch $metamanifest
chmod 644 $metamanifest
if [ "$folder" == "metadata" ] || [ "$folder" == "meta-data" ]
then
sed -i '/$file/d' $metamanifest
echo $file >> $metamanifest
fi
return $?
}
delete_vm_data_file() {
local domrIp=$1
local vmIp=$2
local folder=$3
local file=$4
vmDataFilePath="/var/www/html/$folder/$vmIp/$file"
if [ -f $vmDataFilePath ]; then
rm -rf $vmDataFilePath
fi
return $?
}
vmIp=
folder=
file=
dataFile=
while getopts 'v:F:f:d:' OPTION
do
case $OPTION in
v) vmIp="$OPTARG"
;;
F) folder="$OPTARG"
;;
f) file="$OPTARG"
;;
d) dataFile="$OPTARG"
;;
?) usage
unlock_exit 1 $lock $locked
;;
esac
done
[ "$vmIp" == "" ] || [ "$folder" == "" ] || [ "$file" == "" ] && usage
[ "$folder" != "userdata" ] && [ "$folder" != "metadata" ] && usage
if [ "$dataFile" != "" ]
then
create_htaccess $vmIp $folder $file
if [ $? -gt 0 ]
then
unlock_exit 1 $lock $locked
fi
copy_vm_data_file $vmIp $folder $file $dataFile
else
delete_vm_data_file $vmIp $folder $file
fi
unlock_exit $? $lock $locked