mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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:
parent
b79f949e1b
commit
1767ddac77
@ -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();
|
||||
|
||||
@ -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]))
|
||||
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user