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