1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * RCM module for managing the OS Quiesce event (SUNW_OS) in a 28 * clustered environment. 29 */ 30 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <fcntl.h> 34 #include <string.h> 35 #include <thread.h> 36 #include <synch.h> 37 #include <assert.h> 38 #include <errno.h> 39 #include <libintl.h> 40 #include <sys/param.h> 41 #include <sys/wait.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <sys/cladm.h> 45 #include "rcm_module.h" 46 47 #define SUNW_OS "SUNW_OS" 48 #define OS_USAGE gettext("Sun Cluster") 49 #define OS_SUSPEND_ERR gettext("OS cannot be quiesced on clustered nodes") 50 #define OS_OFFLINE_ERR gettext("Invalid operation: OS cannot be offlined") 51 #define OS_REMOVE_ERR gettext("Invalid operation: OS cannot be removed") 52 53 static int cluster_register(rcm_handle_t *); 54 static int cluster_unregister(rcm_handle_t *); 55 static int cluster_getinfo(rcm_handle_t *, char *, id_t, uint_t, 56 char **, char **, nvlist_t *, rcm_info_t **); 57 static int cluster_suspend(rcm_handle_t *, char *, id_t, 58 timespec_t *, uint_t, char **, rcm_info_t **); 59 static int cluster_resume(rcm_handle_t *, char *, id_t, uint_t, 60 char **, rcm_info_t **); 61 static int cluster_offline(rcm_handle_t *, char *, id_t, uint_t, 62 char **, rcm_info_t **); 63 static int cluster_online(rcm_handle_t *, char *, id_t, uint_t, 64 char **, rcm_info_t **); 65 static int cluster_remove(rcm_handle_t *, char *, id_t, uint_t, 66 char **, rcm_info_t **); 67 68 static int cluster_SUNW_os_registered = 0; 69 70 static struct rcm_mod_ops cluster_ops = 71 { 72 RCM_MOD_OPS_VERSION, 73 cluster_register, 74 cluster_unregister, 75 cluster_getinfo, 76 cluster_suspend, 77 cluster_resume, 78 cluster_offline, 79 cluster_online, 80 cluster_remove, 81 NULL, 82 NULL, 83 NULL 84 }; 85 86 struct rcm_mod_ops * 87 rcm_mod_init() 88 { 89 return (&cluster_ops); 90 } 91 92 const char * 93 rcm_mod_info() 94 { 95 return (gettext("RCM Cluster module 1.3")); 96 } 97 98 int 99 rcm_mod_fini() 100 { 101 return (RCM_SUCCESS); 102 } 103 104 static int 105 cluster_register(rcm_handle_t *hdl) 106 { 107 int bootflags; 108 109 if (cluster_SUNW_os_registered) 110 return (RCM_SUCCESS); 111 112 if (_cladm(CL_INITIALIZE, CL_GET_BOOTFLAG, &bootflags) != 0) { 113 rcm_log_message(RCM_ERROR, 114 gettext("unable to check cluster status\n")); 115 return (RCM_FAILURE); 116 } 117 118 /* attempt to determine if we are in cluster mode */ 119 120 if (bootflags & CLUSTER_BOOTED) { 121 if (rcm_register_interest(hdl, SUNW_OS, 0, NULL) != 122 RCM_SUCCESS) { 123 rcm_log_message(RCM_ERROR, 124 gettext("failed to register\n")); 125 return (RCM_FAILURE); 126 } else { 127 cluster_SUNW_os_registered = 1; 128 rcm_log_message(RCM_DEBUG, "registered " SUNW_OS 129 "\n"); 130 } 131 } 132 133 return (RCM_SUCCESS); 134 } 135 136 static int 137 cluster_unregister(rcm_handle_t *hdl) 138 { 139 140 if (cluster_SUNW_os_registered) { 141 if (rcm_unregister_interest(hdl, SUNW_OS, 0) != 142 RCM_SUCCESS) { 143 rcm_log_message(RCM_ERROR, 144 gettext("failed to unregister")); 145 } 146 cluster_SUNW_os_registered = 0; 147 } 148 return (RCM_SUCCESS); 149 } 150 151 /*ARGSUSED*/ 152 static int 153 cluster_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 154 char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent) 155 { 156 157 assert(rsrcname != NULL && infostr != NULL); 158 159 if ((*infostr = strdup(OS_USAGE)) == NULL) 160 rcm_log_message(RCM_ERROR, gettext("strdup failure\n")); 161 162 return (RCM_SUCCESS); 163 } 164 165 /*ARGSUSED*/ 166 static int 167 cluster_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id, 168 timespec_t *interval, uint_t flags, char **errstr, 169 rcm_info_t **dependent) 170 { 171 if ((*errstr = strdup(OS_SUSPEND_ERR)) == NULL) 172 rcm_log_message(RCM_ERROR, gettext("strdup failure\n")); 173 174 return (RCM_FAILURE); 175 } 176 177 /*ARGSUSED*/ 178 static int 179 cluster_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 180 char **errstr, rcm_info_t **dependent) 181 { 182 return (RCM_SUCCESS); 183 } 184 185 /* 186 * By default, reject offline. If offline request is 187 * forced, attempt to relocate the cluster device. 188 */ 189 /*ARGSUSED*/ 190 static int 191 cluster_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 192 char **errstr, rcm_info_t **dependent) 193 { 194 if ((*errstr = strdup(OS_OFFLINE_ERR)) == NULL) 195 rcm_log_message(RCM_ERROR, gettext("strdup failure\n")); 196 197 return (RCM_FAILURE); 198 } 199 200 /*ARGSUSED*/ 201 static int 202 cluster_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 203 char **errstr, rcm_info_t **dependent) 204 { 205 return (RCM_SUCCESS); 206 } 207 208 /*ARGSUSED*/ 209 static int 210 cluster_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags, 211 char **errstr, rcm_info_t **dependent) 212 { 213 if ((*errstr = strdup(OS_REMOVE_ERR)) == NULL) 214 rcm_log_message(RCM_ERROR, gettext("strdup failure\n")); 215 216 return (RCM_FAILURE); 217 } 218