Skip to content

Commit 7b752c3

Browse files
GutoVeroneziDaniel Augusto Veronezi Salvador
andauthored
Externalize KVM Agent storage's timeout configuration (#5239)
* Externalize KVM Agent storage's timeout configuration * Address @nvazquez review * Add empty line at the end of the agent.properties file Co-authored-by: Daniel Augusto Veronezi Salvador <[email protected]>
1 parent 1f5ee5b commit 7b752c3

File tree

5 files changed

+357
-90
lines changed

5 files changed

+357
-90
lines changed

agent/conf/agent.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,7 @@ iscsi.session.cleanup.enabled=false
266266
# Automatically clean up iscsi sessions not attached to any VM.
267267
# Should be enabled for users using managed storage for example solidfire.
268268
# Should be disabled for users with unmanaged iscsi connections on their hosts
269+
270+
# This parameter specifies the heartbeat update timeout in ms; The default value is 60000ms (1 min).
271+
# Depending on the use case, this timeout might need increasing/decreasing.
272+
# heartbeat.update.timeout=60000
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
package com.cloud.agent.properties;
16+
17+
/**
18+
* Class of constant agent's properties available to configure on
19+
* "agent.properties".
20+
*<br><br>
21+
* Not all available agent properties are defined here, but we should work to
22+
* migrate them on demand to this class.
23+
*
24+
* @param <T> type of the default value.
25+
*/
26+
public class AgentProperties{
27+
28+
/**
29+
* Heartbeat update timeout. <br>
30+
* Data type: int. <br>
31+
* Default value: 60000 (ms).
32+
*/
33+
public static final Property<Integer> HEARTBEAT_UPDATE_TIMEOUT = new Property<Integer>("heartbeat.update.timeout", 60000);
34+
35+
public static class Property <T>{
36+
private final String name;
37+
private final T defaultValue;
38+
39+
private Property(String name, T value) {
40+
this.name = name;
41+
this.defaultValue = value;
42+
}
43+
44+
public String getName() {
45+
return name;
46+
}
47+
48+
public T getDefaultValue() {
49+
return defaultValue;
50+
}
51+
}
52+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
package com.cloud.agent.properties;
16+
17+
import com.cloud.utils.PropertiesUtil;
18+
import java.io.File;
19+
import java.io.IOException;
20+
import org.apache.cloudstack.utils.security.KeyStoreUtils;
21+
import org.apache.commons.beanutils.ConvertUtils;
22+
import org.apache.commons.beanutils.converters.IntegerConverter;
23+
import org.apache.commons.lang3.StringUtils;
24+
import org.apache.log4j.Logger;
25+
26+
/**
27+
* This class provides a facility to read the agent's properties file and get
28+
* its properties, according to the {@link AgentProperties} properties constants.
29+
*
30+
*/
31+
public class AgentPropertiesFileHandler {
32+
33+
private static final Logger logger = Logger.getLogger(AgentPropertiesFileHandler.class);
34+
35+
/**
36+
* This method reads the property in the agent.properties file.
37+
*
38+
* @param property the property to retrieve.
39+
* @return The value of the property. If the property is not available, the
40+
* default defined value will be used.
41+
*/
42+
public static <T> T getPropertyValue(AgentProperties.Property<T> property) {
43+
T defaultValue = property.getDefaultValue();
44+
String name = property.getName();
45+
46+
File agentPropertiesFile = PropertiesUtil.findConfigFile(KeyStoreUtils.AGENT_PROPSFILE);
47+
48+
if (agentPropertiesFile != null) {
49+
try {
50+
String configValue = PropertiesUtil.loadFromFile(agentPropertiesFile).getProperty(name);
51+
if (StringUtils.isNotBlank(configValue)) {
52+
if (defaultValue instanceof Integer) {
53+
ConvertUtils.register(new IntegerConverter(defaultValue), Integer.class);
54+
}
55+
56+
return (T)ConvertUtils.convert(configValue, defaultValue.getClass());
57+
} else {
58+
logger.debug(String.format("Property [%s] has empty or null value. Using default value [%s].", name, defaultValue));
59+
}
60+
} catch (IOException ex) {
61+
logger.debug(String.format("Failed to get property [%s]. Using default value [%s].", name, defaultValue), ex);
62+
}
63+
} else {
64+
logger.debug(String.format("File [%s] was not found, we will use default defined values. Property [%s]: [%s].", KeyStoreUtils.AGENT_PROPSFILE, name, defaultValue));
65+
}
66+
67+
return defaultValue;
68+
}
69+
70+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package com.cloud.agent.properties;
21+
22+
import com.cloud.utils.PropertiesUtil;
23+
import java.io.File;
24+
import java.io.IOException;
25+
import java.util.Properties;
26+
import junit.framework.TestCase;
27+
import org.apache.commons.beanutils.ConvertUtils;
28+
import org.junit.Assert;
29+
import org.junit.Test;
30+
import org.junit.runner.RunWith;
31+
import org.mockito.Mock;
32+
import org.mockito.Mockito;
33+
import org.powermock.api.mockito.PowerMockito;
34+
import org.powermock.core.classloader.annotations.PrepareForTest;
35+
import org.powermock.modules.junit4.PowerMockRunner;
36+
37+
@RunWith(PowerMockRunner.class)
38+
@PrepareForTest({PropertiesUtil.class, ConvertUtils.class})
39+
public class AgentPropertiesFileHandlerTest extends TestCase {
40+
41+
@Mock
42+
AgentProperties.Property<String> agentPropertiesStringMock;
43+
44+
@Mock
45+
AgentProperties.Property<Integer> agentPropertiesIntegerMock;
46+
47+
@Mock
48+
File fileMock;
49+
50+
@Mock
51+
Properties propertiesMock;
52+
53+
@Test
54+
public void validateGetPropertyValueFileNotFoundReturnDefaultValue() throws Exception{
55+
String expectedResult = "default value";
56+
Mockito.doReturn(expectedResult).when(agentPropertiesStringMock).getDefaultValue();
57+
58+
PowerMockito.mockStatic(PropertiesUtil.class);
59+
PowerMockito.doReturn(null).when(PropertiesUtil.class, "findConfigFile", Mockito.anyString());
60+
61+
String result = AgentPropertiesFileHandler.getPropertyValue(agentPropertiesStringMock);
62+
63+
Assert.assertEquals(expectedResult, result);
64+
}
65+
66+
@Test
67+
public void validateGetPropertyValueLoadFromFileThrowsIOExceptionReturnDefaultValue() throws Exception{
68+
String expectedResult = "default value";
69+
Mockito.doReturn(expectedResult).when(agentPropertiesStringMock).getDefaultValue();
70+
71+
PowerMockito.mockStatic(PropertiesUtil.class);
72+
PowerMockito.doReturn(fileMock).when(PropertiesUtil.class, "findConfigFile", Mockito.anyString());
73+
PowerMockito.doThrow(new IOException()).when(PropertiesUtil.class, "loadFromFile", Mockito.any());
74+
75+
String result = AgentPropertiesFileHandler.getPropertyValue(agentPropertiesStringMock);
76+
77+
Assert.assertEquals(expectedResult, result);
78+
}
79+
80+
@Test
81+
public void validateGetPropertyValuePropertyIsEmptyReturnDefaultValue() throws Exception{
82+
String expectedResult = "default value";
83+
Mockito.doReturn(expectedResult).when(agentPropertiesStringMock).getDefaultValue();
84+
Mockito.doReturn("name").when(agentPropertiesStringMock).getName();
85+
86+
PowerMockito.mockStatic(PropertiesUtil.class);
87+
PowerMockito.doReturn(fileMock).when(PropertiesUtil.class, "findConfigFile", Mockito.anyString());
88+
PowerMockito.doReturn(propertiesMock).when(PropertiesUtil.class, "loadFromFile", Mockito.any());
89+
PowerMockito.doReturn("").when(propertiesMock).getProperty(Mockito.anyString());
90+
91+
String result = AgentPropertiesFileHandler.getPropertyValue(agentPropertiesStringMock);
92+
93+
Assert.assertEquals(expectedResult, result);
94+
}
95+
96+
@Test
97+
public void validateGetPropertyValuePropertyIsNullReturnDefaultValue() throws Exception{
98+
String expectedResult = "default value";
99+
Mockito.doReturn(expectedResult).when(agentPropertiesStringMock).getDefaultValue();
100+
Mockito.doReturn("name").when(agentPropertiesStringMock).getName();
101+
102+
PowerMockito.mockStatic(PropertiesUtil.class);
103+
PowerMockito.doReturn(fileMock).when(PropertiesUtil.class, "findConfigFile", Mockito.anyString());
104+
PowerMockito.doReturn(propertiesMock).when(PropertiesUtil.class, "loadFromFile", Mockito.any());
105+
PowerMockito.doReturn(null).when(propertiesMock).getProperty(Mockito.anyString());
106+
107+
String result = AgentPropertiesFileHandler.getPropertyValue(agentPropertiesStringMock);
108+
109+
Assert.assertEquals(expectedResult, result);
110+
}
111+
112+
@Test
113+
public void validateGetPropertyValueValidPropertyReturnPropertyValue() throws Exception{
114+
String expectedResult = "test";
115+
Mockito.doReturn("default value").when(agentPropertiesStringMock).getDefaultValue();
116+
Mockito.doReturn("name").when(agentPropertiesStringMock).getName();
117+
118+
PowerMockito.mockStatic(PropertiesUtil.class);
119+
PowerMockito.doReturn(fileMock).when(PropertiesUtil.class, "findConfigFile", Mockito.anyString());
120+
PowerMockito.doReturn(propertiesMock).when(PropertiesUtil.class, "loadFromFile", Mockito.any());
121+
Mockito.doReturn(expectedResult).when(propertiesMock).getProperty(Mockito.anyString());
122+
123+
String result = AgentPropertiesFileHandler.getPropertyValue(agentPropertiesStringMock);
124+
125+
Assert.assertEquals(expectedResult, result);
126+
}
127+
128+
@Test
129+
public void validateGetPropertyValueValidIntegerPropertyReturnPropertyValue() throws Exception{
130+
Integer expectedResult = 2;
131+
Mockito.doReturn(1).when(agentPropertiesIntegerMock).getDefaultValue();
132+
Mockito.doReturn("name").when(agentPropertiesIntegerMock).getName();
133+
134+
PowerMockito.mockStatic(PropertiesUtil.class);
135+
PowerMockito.doReturn(fileMock).when(PropertiesUtil.class, "findConfigFile", Mockito.anyString());
136+
PowerMockito.doReturn(propertiesMock).when(PropertiesUtil.class, "loadFromFile", Mockito.any());
137+
Mockito.doReturn(String.valueOf(expectedResult)).when(propertiesMock).getProperty(Mockito.anyString());
138+
139+
Integer result = AgentPropertiesFileHandler.getPropertyValue(agentPropertiesIntegerMock);
140+
141+
Assert.assertEquals(expectedResult, result);
142+
}
143+
}

0 commit comments

Comments
 (0)