From fe8d81e24616af4d68065c09393c8026272fd2d6 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 10 May 2011 17:57:22 -0700 Subject: [PATCH] bug 9765: This is NOT an UI bug. This is a server-side bug. UI calls DeployVM API with ServiceOfferingID parameter (NOT ServiceOfferingDescription parameter). Then, server-side gets ServiceOfferingDescription by ServiceOfferingID and send it to DomR WITHTOUT escaping it first. DomR doesn't support full range of unicode character set. Therefore, DomR fails to accept metadata that has non-ascii code (error: "vm_data failed"). This check-in will send Unicode-escaped string of metadata "service-offering", "availability-zone" and "local-hostname" to DomR. Data Consumer of VM-data service needs to unescape the content accordingly. --- .../VirtualNetworkApplianceManagerImpl.java | 7 +++--- utils/src/com/cloud/utils/StringUtils.java | 24 ++++++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index f66a6360623..b06199783fe 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -152,6 +152,7 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.PasswordGenerator; +import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -598,10 +599,10 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); cmd.addVmData("userdata", "user-data", userData); - cmd.addVmData("metadata", "service-offering", serviceOffering); - cmd.addVmData("metadata", "availability-zone", zoneName); + cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering)); + cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName)); cmd.addVmData("metadata", "local-ipv4", guestIpAddress); - cmd.addVmData("metadata", "local-hostname", vmName); + cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vmName)); cmd.addVmData("metadata", "public-ipv4", router.getPublicIpAddress()); cmd.addVmData("metadata", "public-hostname", router.getPublicIpAddress()); cmd.addVmData("metadata", "instance-id", vmInstanceName); diff --git a/utils/src/com/cloud/utils/StringUtils.java b/utils/src/com/cloud/utils/StringUtils.java index ab50829de64..2b3e7ba2ce6 100644 --- a/utils/src/com/cloud/utils/StringUtils.java +++ b/utils/src/com/cloud/utils/StringUtils.java @@ -24,7 +24,11 @@ import java.util.List; // StringUtils exists in Apache Commons Lang, but rather than import the entire JAR to our system, for now // just implement the method needed -public class StringUtils { +public class StringUtils { + private static final char[] hexChar = { + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' + }; + public static String join(Iterable iterable, String delim) { StringBuilder sb = new StringBuilder(); if (iterable != null) { @@ -97,4 +101,22 @@ public class StringUtils { return sb.toString(); } + + public static String unicodeEscape(String s) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if ((c >> 7) > 0) { + sb.append("\\u"); + sb.append(hexChar[(c >> 12) & 0xF]); // append the hex character for the left-most 4-bits + sb.append(hexChar[(c >> 8) & 0xF]); // hex for the second group of 4-bits from the left + sb.append(hexChar[(c >> 4) & 0xF]); // hex for the third group + sb.append(hexChar[c & 0xF]); // hex for the last group, e.g., the right most 4-bits + } + else { + sb.append(c); + } + } + return sb.toString(); + } }