fix: preserve admin-set host state across worker re-registration in makeWorker_
When a worker re-joins and already exists in workermgr, makeWorker_() now overrides the existing slot instead of returning EEXIST. Admin-set flags (LOCKEDU, CLOSED, HIDDEN, CLOSED_BY_ADMIN) survive the override. Add XCE_WORKER_CLOSED_BY_ADMIN flag to distinguish admin-closed hosts from workload-closed ones. worker_ctrl sets/clears it alongside CLOSED. Refactor worker_init/worker_destroy into copy_worker/kill_worker helpers shared by both fresh creation and override paths. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d47b3375e7
commit
febb4a6c4d
6 changed files with 111 additions and 57 deletions
|
|
@ -616,13 +616,13 @@ int worker_ctrl(cluster_t* c, xce_hostctrl_t* ctrl)
|
||||||
if (!(w->host.status & XCE_WORKER_CLOSED)) {
|
if (!(w->host.status & XCE_WORKER_CLOSED)) {
|
||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
w->host.status &= ~XCE_WORKER_CLOSED;
|
w->host.status &= ~(XCE_WORKER_CLOSED | XCE_WORKER_CLOSED_BY_ADMIN);
|
||||||
break;
|
break;
|
||||||
case HOST_CLOSE:
|
case HOST_CLOSE:
|
||||||
if (w->host.status & XCE_WORKER_CLOSED) {
|
if (w->host.status & XCE_WORKER_CLOSED) {
|
||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
w->host.status |= XCE_WORKER_CLOSED;
|
w->host.status |= (XCE_WORKER_CLOSED | XCE_WORKER_CLOSED_BY_ADMIN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
|
|
||||||
|
|
@ -536,21 +536,16 @@ func validateHost(ctx *gin.Context, control int, hostnames []string) (successHos
|
||||||
}
|
}
|
||||||
|
|
||||||
func isHostControlActionAllowed(actionType int, status int) bool {
|
func isHostControlActionAllowed(actionType int, status int) bool {
|
||||||
|
isClosed := (status&models.HOSTSTAT["CLOSED"]) != 0 ||
|
||||||
|
(status&models.HOSTSTAT["CLOSED_BY_ADMIN"]) != 0
|
||||||
switch actionType {
|
switch actionType {
|
||||||
case 1: // open strictly
|
case 1: // open
|
||||||
if status&models.HOSTSTAT["CLOSED"] != 0 {
|
return isClosed
|
||||||
return true
|
|
||||||
}
|
|
||||||
case 2: // close
|
case 2: // close
|
||||||
if (status & models.HOSTSTAT["CLOSED"]) != 0 {
|
return !isClosed
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
func preCheckHostControlRequest(req *models.HostControlRequest) (bool, error) {
|
func preCheckHostControlRequest(req *models.HostControlRequest) (bool, error) {
|
||||||
logger.Debug("Enter preCheckHostControlRequest")
|
logger.Debug("Enter preCheckHostControlRequest")
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,19 @@ const (
|
||||||
var SupportedHostActions = []string{"open", "close"}
|
var SupportedHostActions = []string{"open", "close"}
|
||||||
|
|
||||||
var HOSTSTAT = map[string]int{
|
var HOSTSTAT = map[string]int{
|
||||||
"UNAVAIL": 0x00010000,
|
"UNAVAIL": 0x00010000,
|
||||||
"LOCKEDU": 0x00020000,
|
"LOCKEDU": 0x00020000,
|
||||||
"LOCKEDW": 0x00040000,
|
"LOCKEDW": 0x00040000,
|
||||||
"BUSY": 0x00080000,
|
"BUSY": 0x00080000,
|
||||||
"CLOSED": 0x00100000,
|
"CLOSED": 0x00100000,
|
||||||
|
"CLOSED_BY_ADMIN": 0x00400000,
|
||||||
}
|
}
|
||||||
|
|
||||||
func HostStateStr(state int) string {
|
func HostStateStr(state int) string {
|
||||||
if (state & HOSTSTAT["UNAVAIL"]) != 0 {
|
if (state & HOSTSTAT["UNAVAIL"]) != 0 {
|
||||||
return "UNAVAIL"
|
return "UNAVAIL"
|
||||||
|
} else if (state & HOSTSTAT["CLOSED_BY_ADMIN"]) != 0 {
|
||||||
|
return "CLOSED_BY_ADMIN"
|
||||||
} else if (state & HOSTSTAT["CLOSED"]) != 0 {
|
} else if (state & HOSTSTAT["CLOSED"]) != 0 {
|
||||||
return "CLOSED"
|
return "CLOSED"
|
||||||
} else if (state & HOSTSTAT["BUSY"]) != 0 {
|
} else if (state & HOSTSTAT["BUSY"]) != 0 {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@ func TestHostStateStr(t *testing.T) {
|
||||||
state: HOSTSTAT["CLOSED"],
|
state: HOSTSTAT["CLOSED"],
|
||||||
want: "CLOSED",
|
want: "CLOSED",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "CLOSED_BY_ADMIN flag",
|
||||||
|
state: HOSTSTAT["CLOSED_BY_ADMIN"],
|
||||||
|
want: "CLOSED_BY_ADMIN",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "BUSY flag",
|
name: "BUSY flag",
|
||||||
state: HOSTSTAT["BUSY"],
|
state: HOSTSTAT["BUSY"],
|
||||||
|
|
@ -48,6 +53,11 @@ func TestHostStateStr(t *testing.T) {
|
||||||
state: HOSTSTAT["UNAVAIL"] | HOSTSTAT["CLOSED"],
|
state: HOSTSTAT["UNAVAIL"] | HOSTSTAT["CLOSED"],
|
||||||
want: "UNAVAIL", // UNAVAIL takes priority
|
want: "UNAVAIL", // UNAVAIL takes priority
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "combined CLOSED+CLOSED_BY_ADMIN flags",
|
||||||
|
state: HOSTSTAT["CLOSED"] | HOSTSTAT["CLOSED_BY_ADMIN"],
|
||||||
|
want: "CLOSED_BY_ADMIN", // CLOSED_BY_ADMIN overrides generic CLOSED
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
||||||
|
|
@ -172,11 +172,13 @@ typedef struct {
|
||||||
#define XCE_WORKER_LOCKEDW (0x00040000)
|
#define XCE_WORKER_LOCKEDW (0x00040000)
|
||||||
#define XCE_WORKER_BUSY (0x00080000)
|
#define XCE_WORKER_BUSY (0x00080000)
|
||||||
#define XCE_WORKER_CLOSED (0x00100000)
|
#define XCE_WORKER_CLOSED (0x00100000)
|
||||||
#define XCE_WORKER_HIDDEN (0x00200000) /* Admin explicitly removed — invisible but not yet cleaned up */
|
#define XCE_WORKER_HIDDEN (0x00200000) /* Admin explicitly removed — invisible but not yet cleaned up */
|
||||||
|
#define XCE_WORKER_CLOSED_BY_ADMIN (0x00400000) /* Admin closed — host closed explicitly by admin */
|
||||||
|
|
||||||
#define IS_WORKER_UNAVAIL(status) (((status) & XCE_WORKER_UNAVAIL) != 0)
|
#define IS_WORKER_UNAVAIL(status) (((status) & XCE_WORKER_UNAVAIL) != 0)
|
||||||
#define IS_WORKER_LOCKEDU(status) (((status) & XCE_WORKER_LOCKEDU) != 0)
|
#define IS_WORKER_LOCKEDU(status) (((status) & XCE_WORKER_LOCKEDU) != 0)
|
||||||
#define IS_WORKER_LOCKEDW(status) (((status) & XCE_WORKER_LOCKEDW) != 0)
|
#define IS_WORKER_LOCKEDW(status) (((status) & XCE_WORKER_LOCKEDW) != 0)
|
||||||
|
#define IS_WORKER_CLOSED_BY_ADMIN(status) (((status) & XCE_WORKER_CLOSED_BY_ADMIN) != 0)
|
||||||
#define IS_WORKER_LOCKED(status) \
|
#define IS_WORKER_LOCKED(status) \
|
||||||
(IS_WORKER_LOCKEDU(status) || IS_WORKER_LOCKEDW(status))
|
(IS_WORKER_LOCKEDU(status) || IS_WORKER_LOCKEDW(status))
|
||||||
#define IS_WORKER_BUSY(status) (((status) & XCE_WORKER_BUSY) != 0)
|
#define IS_WORKER_BUSY(status) (((status) & XCE_WORKER_BUSY) != 0)
|
||||||
|
|
|
||||||
116
src/lib/wobj.c
116
src/lib/wobj.c
|
|
@ -22,12 +22,34 @@ static size_t worker_datasize(va_list ap)
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int worker_init(meta_obj_t* obj, va_list ap)
|
static void kill_worker(worker_t* w)
|
||||||
{
|
{
|
||||||
worker_t* dst = RTTI_OBJ_TO_DATA(worker_t, obj);
|
dereference(w->host.name);
|
||||||
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
|
||||||
xce_worker_t* src = va_arg(ap, xce_worker_t*);
|
|
||||||
|
|
||||||
|
if (w->host.attrs != NULL) {
|
||||||
|
dereference(w->host.attrs->hosttype);
|
||||||
|
dereference(w->host.attrs->hostmodel);
|
||||||
|
FREEUP(w->host.attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->host.dispatch_window_config != NULL) {
|
||||||
|
free_timewindow_config(w->host.dispatch_window_config);
|
||||||
|
w->host.dispatch_window_config = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->host.thresholds != NULL) {
|
||||||
|
free_resource_thresholds(w->host.thresholds, w->host.nthresholds);
|
||||||
|
w->host.thresholds = NULL;
|
||||||
|
w->host.nthresholds = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
zarray_fini(&(w->host.resvals));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int copy_worker(worker_t* dst, xce_worker_t* src)
|
||||||
|
{
|
||||||
if ((src == NULL) || (src->attrs == NULL)) {
|
if ((src == NULL) || (src->attrs == NULL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -55,6 +77,42 @@ static int worker_init(meta_obj_t* obj, va_list ap)
|
||||||
dst->host.nresvals_to_sched = 0;
|
dst->host.nresvals_to_sched = 0;
|
||||||
dst->host.resvals_to_sched = NULL;
|
dst->host.resvals_to_sched = NULL;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int override_worker(worker_t* dst, xce_worker_t* w)
|
||||||
|
{
|
||||||
|
#define XCE_WORKER_ADMIN_MASK \
|
||||||
|
(XCE_WORKER_LOCKEDU | XCE_WORKER_CLOSED | XCE_WORKER_HIDDEN | XCE_WORKER_CLOSED_BY_ADMIN)
|
||||||
|
uint32_t admin_status = 0;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
admin_status = dst->host.status & XCE_WORKER_ADMIN_MASK;
|
||||||
|
|
||||||
|
kill_worker(dst);
|
||||||
|
|
||||||
|
rc = copy_worker(dst, w);
|
||||||
|
if (rc >= 0) {
|
||||||
|
dst->host.status |= admin_status;
|
||||||
|
dst->ep = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
#undef XCE_WORKER_ADMIN_MASK
|
||||||
|
}
|
||||||
|
|
||||||
|
static int worker_init(meta_obj_t* obj, va_list ap)
|
||||||
|
{
|
||||||
|
worker_t* dst = RTTI_OBJ_TO_DATA(worker_t, obj);
|
||||||
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
||||||
|
xce_worker_t* src = va_arg(ap, xce_worker_t*);
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = copy_worker(dst, src);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
my_rwlock_init(&(priv->lock));
|
my_rwlock_init(&(priv->lock));
|
||||||
priv->refcount = 1;
|
priv->refcount = 1;
|
||||||
|
|
||||||
|
|
@ -66,26 +124,7 @@ static void worker_destroy(meta_obj_t* obj)
|
||||||
worker_t* w = RTTI_OBJ_TO_DATA(worker_t, obj);
|
worker_t* w = RTTI_OBJ_TO_DATA(worker_t, obj);
|
||||||
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
worker_private_t* priv = (worker_private_t*)RTTI_OBJ_TO_PRIV(obj);
|
||||||
|
|
||||||
dereference(w->host.name);
|
kill_worker(w);
|
||||||
|
|
||||||
if (w->host.attrs != NULL) {
|
|
||||||
dereference(w->host.attrs->hosttype);
|
|
||||||
dereference(w->host.attrs->hostmodel);
|
|
||||||
FREEUP(w->host.attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w->host.dispatch_window_config != NULL) {
|
|
||||||
free_timewindow_config(w->host.dispatch_window_config);
|
|
||||||
w->host.dispatch_window_config = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w->host.thresholds != NULL) {
|
|
||||||
free_resource_thresholds(w->host.thresholds, w->host.nthresholds);
|
|
||||||
w->host.thresholds = NULL;
|
|
||||||
w->host.nthresholds = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
zarray_fini(&(w->host.resvals));
|
|
||||||
|
|
||||||
my_rwlock_fini(&(priv->lock));
|
my_rwlock_fini(&(priv->lock));
|
||||||
memset(priv, 0x0, sizeof(*priv));
|
memset(priv, 0x0, sizeof(*priv));
|
||||||
|
|
@ -163,9 +202,10 @@ static typeinfo_t worker_type = {
|
||||||
static worker_t* makeWorker_(var workermgr, xce_worker_t* w)
|
static worker_t* makeWorker_(var workermgr, xce_worker_t* w)
|
||||||
{
|
{
|
||||||
worker_t* worker = NULL;
|
worker_t* worker = NULL;
|
||||||
|
worker_t* w1 = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
rc = key_find(workermgr, (void*)w->name, (void**)&worker);
|
rc = key_find(workermgr, (void*)w->name, (void**)&w1);
|
||||||
|
|
||||||
if ((rc < 0) && (rc != -ENOENT)) {
|
if ((rc < 0) && (rc != -ENOENT)) {
|
||||||
errno = -rc;
|
errno = -rc;
|
||||||
|
|
@ -174,20 +214,24 @@ static worker_t* makeWorker_(var workermgr, xce_worker_t* w)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
errno = EEXIST;
|
rc = override_worker(w1, w);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
worker = makeInstance(&worker_type, w);
|
|
||||||
if (worker != NULL) {
|
|
||||||
rc = key_add(workermgr, (void*)worker->host.name, (void*)worker);
|
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
destroy(worker);
|
|
||||||
|
|
||||||
errno = -rc;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
worker = w1;
|
||||||
|
} else {
|
||||||
|
worker = makeInstance(&worker_type, w);
|
||||||
|
if (worker != NULL) {
|
||||||
|
rc = key_add(workermgr, (void*)worker->host.name, (void*)worker);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
destroy(worker);
|
||||||
|
|
||||||
|
errno = -rc;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return worker;
|
return worker;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue