Skip to content

Commit 67ebb44

Browse files
committed
KVM: Rolling maintenance
1 parent 3220705 commit 67ebb44

37 files changed

Lines changed: 1754 additions & 11 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/python
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+
# http://www.apache.org/licenses/LICENSE-2.0
10+
# Unless required by applicable law or agreed to in writing,
11+
# software distributed under the License is distributed on an
12+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13+
# KIND, either express or implied. See the License for the
14+
# specific language governing permissions and limitations
15+
# under the License.
16+
17+
from subprocess import *
18+
import sys
19+
import time
20+
import logging
21+
22+
LOG_FILE='/var/log/cloudstack/agent/rolling-maintenance.log'
23+
24+
logging.basicConfig(filename=LOG_FILE,
25+
filemode='a',
26+
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
27+
datefmt='%H:%M:%S',
28+
level=logging.INFO)
29+
logger = logging.getLogger('rolling-maintenance')
30+
31+
def execute_script(stage, script):
32+
logger.info("Executing script: %s for stage: %s" % (script, stage))
33+
34+
try:
35+
command = '. ' + script
36+
pout = Popen(command, shell=True, stdout=PIPE)
37+
exitStatus = pout.wait()
38+
output = pout.communicate()[0]
39+
40+
if exitStatus == 0:
41+
logger.info("Successful execution of %s" % script)
42+
return {"success": "True", "message": output.strip()}
43+
else:
44+
logger.info("Script execution failed: %s" % script)
45+
return {"success": "False", "message": output.strip()}
46+
except Exception as e:
47+
logger.error("Error in script: %s for stage: %s" % (script, e))
48+
sys.exit(1)
49+
50+
if __name__ == '__main__':
51+
if len(sys.argv) != 2:
52+
logger.error("Wrong number of parameters received, STAGE,SCRIPT expected")
53+
sys.exit(0)
54+
55+
args = sys.argv[1]
56+
params = args.split(',')
57+
stage = params[0]
58+
script = params[1]
59+
logger.info("Received parameters: stage: %s and script: %s" % (stage, script))
60+
61+
execute_script(stage, script)
62+
logger.info("Finished executing stage: %s (file: %s)" % (stage, script))

agent/conf/agent.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ domr.scripts.dir=scripts/network/domr/kvm
115115
# set the hypervisor type, values are: kvm, lxc
116116
hypervisor.type=kvm
117117

118+
# set the rolling maintenance hook scripts directory
119+
#rolling.maintenance.hooks.dir=/etc/cloudstack/agent/hooks.d
120+
121+
# disable the rolling maintenance service execution
122+
#rolling.maintenance.service.executor.disabled=true
123+
118124
# set the hypervisor URI. Usually there is no need for changing this
119125
# For KVM: qemu:///system
120126
# For LXC: lxc:///

api/src/main/java/com/cloud/dc/DataCenter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Map;
2020

21+
import com.cloud.resource.RollingMaintenanceEntity;
2122
import org.apache.cloudstack.acl.InfrastructureEntity;
2223
import org.apache.cloudstack.kernel.Partition;
2324

@@ -26,7 +27,7 @@
2627
/**
2728
*
2829
*/
29-
public interface DataCenter extends InfrastructureEntity, Grouping, Partition {
30+
public interface DataCenter extends InfrastructureEntity, Grouping, Partition, RollingMaintenanceEntity {
3031

3132
public enum NetworkType {
3233
Basic, Advanced,

api/src/main/java/com/cloud/dc/Pod.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.dc;
1818

19+
import com.cloud.resource.RollingMaintenanceEntity;
1920
import org.apache.cloudstack.acl.InfrastructureEntity;
2021
import org.apache.cloudstack.api.Identity;
2122
import org.apache.cloudstack.api.InternalIdentity;
@@ -26,7 +27,7 @@
2627
* Represents one pod in the cloud stack.
2728
*
2829
*/
29-
public interface Pod extends InfrastructureEntity, Grouping, Identity, InternalIdentity {
30+
public interface Pod extends InfrastructureEntity, Grouping, Identity, InternalIdentity, RollingMaintenanceEntity {
3031

3132
String getCidrAddress();
3233

api/src/main/java/com/cloud/event/EventTypes.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@
7272
import org.apache.cloudstack.acl.Role;
7373
import org.apache.cloudstack.acl.RolePermission;
7474
import org.apache.cloudstack.annotation.Annotation;
75+
import org.apache.cloudstack.api.response.ClusterResponse;
76+
import org.apache.cloudstack.api.response.HostResponse;
77+
import org.apache.cloudstack.api.response.PodResponse;
78+
import org.apache.cloudstack.api.response.ZoneResponse;
7579
import org.apache.cloudstack.config.Configuration;
7680
import org.apache.cloudstack.ha.HAConfig;
7781
import org.apache.cloudstack.usage.Usage;
@@ -574,6 +578,13 @@ public class EventTypes {
574578
// Diagnostics Events
575579
public static final String EVENT_SYSTEM_VM_DIAGNOSTICS = "SYSTEM.VM.DIAGNOSTICS";
576580

581+
// Rolling Maintenance
582+
public static final String EVENT_START_ROLLING_MAINTENANCE = "SYSTEM.ROLLING.MAINTENANCE";
583+
public static final String EVENT_HOST_ROLLING_MAINTENANCE = "HOST.ROLLING.MAINTENANCE";
584+
public static final String EVENT_CLUSTER_ROLLING_MAINTENANCE = "CLUSTER.ROLLING.MAINTENANCE";
585+
public static final String EVENT_POD_ROLLING_MAINTENANCE = "POD.ROLLING.MAINTENANCE";
586+
public static final String EVENT_ZONE_ROLLING_MAINTENANCE = "ZONE.ROLLING.MAINTENANCE";
587+
577588
static {
578589

579590
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -969,6 +980,11 @@ public class EventTypes {
969980
entityEventDetails.put(EVENT_TEMPLATE_DIRECT_DOWNLOAD_FAILURE, VirtualMachineTemplate.class);
970981
entityEventDetails.put(EVENT_ISO_DIRECT_DOWNLOAD_FAILURE, "Iso");
971982
entityEventDetails.put(EVENT_SYSTEM_VM_DIAGNOSTICS, VirtualMachine.class);
983+
984+
entityEventDetails.put(EVENT_ZONE_ROLLING_MAINTENANCE, ZoneResponse.class);
985+
entityEventDetails.put(EVENT_POD_ROLLING_MAINTENANCE, PodResponse.class);
986+
entityEventDetails.put(EVENT_CLUSTER_ROLLING_MAINTENANCE, ClusterResponse.class);
987+
entityEventDetails.put(EVENT_HOST_ROLLING_MAINTENANCE, HostResponse.class);
972988
}
973989

974990
public static String getEntityForEvent(String eventName) {

api/src/main/java/com/cloud/host/Host.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2020
import com.cloud.resource.ResourceState;
21+
import com.cloud.resource.RollingMaintenanceEntity;
2122
import com.cloud.utils.fsm.StateObject;
2223
import org.apache.cloudstack.api.Identity;
2324
import org.apache.cloudstack.ha.HAResource;
@@ -28,7 +29,7 @@
2829
/**
2930
* Host represents one particular host server.
3031
*/
31-
public interface Host extends StateObject<Status>, Identity, Partition, HAResource {
32+
public interface Host extends StateObject<Status>, Identity, Partition, HAResource, RollingMaintenanceEntity {
3233
public enum Type {
3334
Storage(false), Routing(false), SecondaryStorage(false), SecondaryStorageCmdExecutor(false), ConsoleProxy(true), ExternalFirewall(false), ExternalLoadBalancer(
3435
false), ExternalVirtualSwitchSupervisor(false), PxeServer(false), BaremetalPxe(false), BaremetalDhcp(false), TrafficMonitor(false), NetScalerControlCenter(false),

api/src/main/java/com/cloud/org/Cluster.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818

1919
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2020
import com.cloud.org.Managed.ManagedState;
21+
import com.cloud.resource.RollingMaintenanceEntity;
2122
import org.apache.cloudstack.kernel.Partition;
2223

23-
public interface Cluster extends Grouping, Partition {
24+
public interface Cluster extends Grouping, Partition, RollingMaintenanceEntity {
2425
public static enum ClusterType {
2526
CloudManaged, ExternalManaged;
2627
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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.resource;
18+
19+
public interface RollingMaintenanceEntity {
20+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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.resource;
18+
19+
import com.cloud.utils.Pair;
20+
import com.cloud.utils.exception.CloudRuntimeException;
21+
import org.apache.cloudstack.api.command.admin.resource.StartRollingMaintenanceCmd;
22+
import org.apache.cloudstack.framework.config.ConfigKey;
23+
import org.apache.cloudstack.framework.config.Configurable;
24+
25+
import java.util.List;
26+
27+
public interface RollingMaintenanceManager extends Configurable {
28+
29+
ConfigKey<Integer> RollingMaintenanceTimeout = new ConfigKey<>("Advanced", Integer.class,
30+
"rolling.maintenance.timeout", "30",
31+
"Wait timeout (in seconds) for rolling maintenance updates from hosts",
32+
true, ConfigKey.Scope.Global);
33+
34+
enum Stage {
35+
PreFlight, PreMaintenance, Maintenance, PostMaintenance;
36+
37+
public Stage next() {
38+
switch (this) {
39+
case PreFlight:
40+
return PreMaintenance;
41+
case PreMaintenance:
42+
return Maintenance;
43+
case Maintenance:
44+
return PostMaintenance;
45+
case PostMaintenance:
46+
return null;
47+
}
48+
throw new CloudRuntimeException("Unexpected stage: " + this);
49+
}
50+
}
51+
52+
enum ResourceType {
53+
Pod, Cluster, Zone, Host
54+
}
55+
56+
Pair<Boolean, String> startRollingMaintenance(StartRollingMaintenanceCmd cmd);
57+
Pair<ResourceType, List<Long>> getResourceTypeIdPair(StartRollingMaintenanceCmd cmd);
58+
}

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class ApiConstants {
6363
public static final String CLEANUP = "cleanup";
6464
public static final String MAKEREDUNDANT = "makeredundant";
6565
public static final String CLUSTER_ID = "clusterid";
66+
public static final String CLUSTER_IDS = "clusterids";
6667
public static final String CLUSTER_NAME = "clustername";
6768
public static final String CLUSTER_TYPE = "clustertype";
6869
public static final String CN = "cn";
@@ -158,6 +159,7 @@ public class ApiConstants {
158159
public static final String HEALTH = "health";
159160
public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage";
160161
public static final String HOST_ID = "hostid";
162+
public static final String HOST_IDS = "hostids";
161163
public static final String HOST_NAME = "hostname";
162164
public static final String HYPERVISOR = "hypervisor";
163165
public static final String INLINE = "inline";
@@ -245,6 +247,7 @@ public class ApiConstants {
245247
public static final String PASSWORD_ENABLED = "passwordenabled";
246248
public static final String SSHKEY_ENABLED = "sshkeyenabled";
247249
public static final String PATH = "path";
250+
public static final String PAYLOAD = "payload";
248251
public static final String POD_ID = "podid";
249252
public static final String POD_NAME = "podname";
250253
public static final String POD_IDS = "podids";

0 commit comments

Comments
 (0)