Skip to content

Commit 8602340

Browse files
committed
Merge remote-tracking branch 'apache/4.22' into improve-error-messages
2 parents 2fdc492 + 51c5249 commit 8602340

23 files changed

Lines changed: 644 additions & 41 deletions

File tree

‎api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportVmCmd.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
9292

9393
@Parameter(name = ApiConstants.DISK_PATH,
9494
type = CommandType.STRING,
95-
description = "path of the disk image")
95+
description = "path of the disk image. It is the file name on file based storage pools (NFS, Local, SharedMountPoint), and the image name on RBD storage pools")
9696
private String diskPath;
9797

9898
@Parameter(name = ApiConstants.IMPORT_SOURCE,

‎api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmd.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public class ImportVolumeCmd extends BaseAsyncCmd {
6363
@Parameter(name = ApiConstants.PATH,
6464
type = BaseCmd.CommandType.STRING,
6565
required = true,
66-
description = "the path of the volume")
66+
description = "the path of the volume. It is the file name on file based storage pools (NFS, Local, SharedMountPoint), and the image name on RBD storage pools")
6767
private String path;
6868

6969
@Parameter(name = ApiConstants.NAME,
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.transport.compat;
18+
19+
import com.cloud.utils.StringUtils;
20+
import com.cloud.utils.exception.CloudRuntimeException;
21+
import com.google.gson.Gson;
22+
import com.google.gson.JsonElement;
23+
import com.google.gson.JsonObject;
24+
import com.google.gson.JsonSerializationContext;
25+
import com.google.gson.JsonSerializer;
26+
27+
import java.lang.reflect.Type;
28+
import java.util.LinkedHashMap;
29+
import java.util.Map;
30+
31+
/**
32+
* JSON serializer adapter for transport classes (com.cloud.agent.api.to.*) that ensures backward compatibility
33+
* with older Agent versions due to rename of the fields
34+
* (see https://github.com/apache/cloudstack/pull/10514)
35+
*
36+
* This class does not build its own Gson instance: doing so would silently drop whichever exclusion
37+
* strategy (e.g. log redaction) and sibling compat adaptors (for nested TOs) the enclosing Gson was
38+
* configured with. Instead, whoever registers an instance of this class into a GsonBuilder is
39+
* responsible for also calling {@link #initGson(Gson)} with a Gson that (a) carries that same
40+
* exclusion strategy and (b) has adapters registered for any nested TO types that also need field
41+
* renaming, but not for this adaptor's own type (to avoid infinite recursion). See
42+
* {@link com.cloud.serializer.GsonHelper#setDefaultGsonConfig(com.google.gson.GsonBuilder)}.
43+
*/
44+
public class AbstractTOAdaptor<T> implements JsonSerializer<T> {
45+
private Gson gson;
46+
private Map<String, String> fieldMappings;
47+
48+
protected AbstractTOAdaptor(String... fields) {
49+
this.fieldMappings = new LinkedHashMap<>();
50+
for (int i = 0; i + 1 < fields.length; i += 2) {
51+
String sourceField = fields[i];
52+
String destinationField = fields[i + 1];
53+
// skip empty fields
54+
if (StringUtils.isBlank(sourceField) || StringUtils.isBlank(destinationField)) {
55+
continue;
56+
}
57+
this.fieldMappings.put(sourceField, destinationField);
58+
}
59+
if (this.fieldMappings.isEmpty()) {
60+
throw new CloudRuntimeException("Field mappings must not be empty");
61+
}
62+
}
63+
64+
public void initGson(Gson gson) {
65+
this.gson = gson;
66+
}
67+
68+
@Override
69+
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
70+
if (src == null) {
71+
return null;
72+
}
73+
JsonElement tree = gson.toJsonTree(src);
74+
if (tree.isJsonObject()) {
75+
JsonObject obj = tree.getAsJsonObject();
76+
for (Map.Entry<String, String> field : fieldMappings.entrySet()) {
77+
String sourceField = field.getKey();
78+
String destinationField = field.getValue();
79+
if (obj.has(sourceField)) {
80+
obj.add(destinationField, obj.get(sourceField));
81+
}
82+
}
83+
}
84+
return tree;
85+
}
86+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.transport.compat;
18+
19+
import com.cloud.agent.api.to.DiskTO;
20+
21+
/**
22+
* See {@link AbstractTOAdaptor}.
23+
*/
24+
public class DiskTOAdaptor extends AbstractTOAdaptor<DiskTO> {
25+
public DiskTOAdaptor() {
26+
super("details", "_details");
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.transport.compat;
18+
19+
import com.cloud.agent.api.MigrateCommand;
20+
21+
/**
22+
* See {@link AbstractTOAdaptor}.
23+
*/
24+
public class MigrateCommandAdaptor extends AbstractTOAdaptor<MigrateCommand> {
25+
public MigrateCommandAdaptor() {
26+
super("destinationIp", "destIp", "windows", "isWindows", "virtualMachine", "vmTO");
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.transport.compat;
18+
19+
import com.cloud.agent.api.to.NetworkTO;
20+
21+
/**
22+
* See {@link AbstractTOAdaptor}.
23+
*/
24+
public class NetworkTOAdaptor extends AbstractTOAdaptor<NetworkTO> {
25+
public NetworkTOAdaptor() {
26+
super("securityGroupEnabled", "isSecurityGroupEnabled");
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.agent.transport.compat;
18+
19+
import com.cloud.agent.api.to.VirtualMachineTO;
20+
21+
/**
22+
* See {@link AbstractTOAdaptor}.
23+
*/
24+
public class VirtualMachineTOAdaptor extends AbstractTOAdaptor<VirtualMachineTO> {
25+
26+
public VirtualMachineTOAdaptor() {
27+
super("details", "params");
28+
}
29+
}

‎core/src/main/java/com/cloud/serializer/GsonHelper.java‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121

2222
import java.util.List;
2323

24+
import com.cloud.agent.api.MigrateCommand;
25+
import com.cloud.agent.api.to.DiskTO;
26+
import com.cloud.agent.api.to.NetworkTO;
27+
import com.cloud.agent.api.to.VirtualMachineTO;
28+
import com.cloud.agent.transport.compat.DiskTOAdaptor;
29+
import com.cloud.agent.transport.compat.MigrateCommandAdaptor;
30+
import com.cloud.agent.transport.compat.NetworkTOAdaptor;
31+
import com.cloud.agent.transport.compat.VirtualMachineTOAdaptor;
2432
import com.cloud.hypervisor.Hypervisor;
2533
import org.apache.cloudstack.transport.HypervisorTypeAdaptor;
2634
import org.apache.logging.log4j.Logger;
@@ -78,6 +86,42 @@ public static Gson setDefaultGsonConfig(GsonBuilder builder) {
7886
}.getType(), new NwGroupsCommandTypeAdaptor());
7987
builder.registerTypeAdapter(Storage.StoragePoolType.class, new StoragePoolTypeAdaptor());
8088
builder.registerTypeAdapter(Hypervisor.HypervisorType.class, new HypervisorTypeAdaptor());
89+
90+
// added for compatibility purposes, remove after all Agents migrate to the new version
91+
//
92+
// Each compat adaptor below needs a "base" Gson to run its own reflective (pre-rename)
93+
// serialization through, so that nested TOs are renamed too and the exclusion strategy set
94+
// on `builder` (e.g. log redaction) is honoured consistently at every nesting level. That base
95+
// Gson is built incrementally off the same builder, snapshotted (via builder.create()) just
96+
// before each adaptor's own type is registered on it, so it carries every sibling adaptor it
97+
// can nest without ever routing back into itself and recursing forever.
98+
DiskTOAdaptor diskAdaptor = new DiskTOAdaptor();
99+
NetworkTOAdaptor netAdaptor = new NetworkTOAdaptor();
100+
VirtualMachineTOAdaptor vmAdaptor = new VirtualMachineTOAdaptor();
101+
MigrateCommandAdaptor migrateAdaptor = new MigrateCommandAdaptor();
102+
103+
// DiskTO and NetworkTO don't nest any other compat TO, so the plain config built so far is
104+
// already the correct base Gson for them.
105+
Gson leafDelegateGson = builder.create();
106+
diskAdaptor.initGson(leafDelegateGson);
107+
netAdaptor.initGson(leafDelegateGson);
108+
109+
// VirtualMachineTO nests DiskTO[] and NicTO[] (NicTO extends NetworkTO), so its base Gson needs
110+
// Disk/Network adapters too. registerTypeHierarchyAdapter is used for NetworkTO so that the
111+
// NicTO[]-declared "nics" field is matched via its supertype.
112+
builder.registerTypeAdapter(DiskTO.class, diskAdaptor);
113+
builder.registerTypeHierarchyAdapter(NetworkTO.class, netAdaptor);
114+
Gson vmDelegateGson = builder.create();
115+
vmAdaptor.initGson(vmDelegateGson);
116+
117+
// MigrateCommand nests a VirtualMachineTO, so its base Gson needs the VirtualMachineTO adapter
118+
// (which already renames the nested disks/nics above).
119+
builder.registerTypeAdapter(VirtualMachineTO.class, vmAdaptor);
120+
Gson migrateDelegateGson = builder.create();
121+
migrateAdaptor.initGson(migrateDelegateGson);
122+
123+
builder.registerTypeAdapter(MigrateCommand.class, migrateAdaptor);
124+
81125
Gson gson = builder.create();
82126
dsAdaptor.initGson(gson);
83127
dtAdaptor.initGson(gson);

0 commit comments

Comments
 (0)