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