[1768] in Moira
Re: proposed moira schema changes and queries for
daemon@ATHENA.MIT.EDU (Qing Dong)
Tue Apr 24 11:50:06 2001
Message-Id: <200104241550.LAA12964@melbourne-city-street.mit.edu>
Date: Tue, 24 Apr 2001 11:45:14 -0400
To: Garry Zacheiss <zacheiss@mit.edu>
From: Qing Dong <dongq@MIT.EDU>
Cc: moiradev@mit.edu
In-Reply-To: <200104240500.BAA182243@oliver.mit.edu>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Garry, thanks for the suggestion. Here are the new diffs for the modified
files.
Qing
Index: mr_server.h
===================================================================
RCS file:
\\dongq-afs\all\athena.mit.edu\astaff\project\moiradev\repository/moira/serv
er/mr_server.h,v
retrieving revision 1.55
diff -c -r1.55 mr_server.h
*** mr_server.h 2000/09/25 22:48:48 1.55
--- mr_server.h 2001/04/24 15:07:35
***************
*** 152,157 ****
--- 152,158 ----
int access_snt(struct query *q, char *argv[], client *cl);
int access_printer(struct query *q, char *argv[], client *cl);
int access_zephyr(struct query *q, char *argv[], client *cl);
+ int access_container(struct query *q, char *argv[], client *cl);
/* prototypes from qfollow.pc */
int followup_fix_modby(struct query *q, struct save_queue *sq,
***************
*** 187,192 ****
--- 188,196 ----
int followup_gpsv(struct query *q, struct save_queue *sq, struct validate
*v,
int (*action)(int, char **, void *), void *actarg,
client *cl);
+ int followup_gcon(struct query *q, struct save_queue *sq, struct validate
*v,
+ int (*action)(int, char **, void *), void *actarg,
+ client *cl);
int followup_ausr(struct query *q, char *argv[], client *cl);
int followup_aqot(struct query *q, char *argv[], client *cl);
***************
*** 231,236 ****
--- 235,241 ----
int setup_uhha(struct query *q, char *argv[], client *cl);
int setup_aprn(struct query *q, char *argv[], client *cl);
int setup_dpsv(struct query *q, char *argv[], client *cl);
+ int setup_dcon(struct query *q, char *argv[], client *cl);
/* prototypes from qsupport.pc */
int set_pobox(struct query *q, char *argv[], client *cl);
***************
*** 240,245 ****
--- 245,251 ----
int tag_member_of_list(struct query *q, char *argv[], client *cl);
int register_user(struct query *q, char *argv[], client *cl);
int do_user_reservation(struct query *q, char *argv[], client *cl);
+ int update_container(struct query *q, char *argv[], client *cl);
int get_ace_use(struct query *q, char **argv, client *cl,
int (*action)(int, char *[], void *), void *actarg);
***************
*** 263,268 ****
--- 269,281 ----
int get_user_by_reservation(struct query *q, char **argv, client *cl,
int (*action)(int, char *[], void *),
void *actarg);
+ int get_machines_of_container(struct query *q, char **argv, client *cl,
+ int (*action)(int, char *[], void *),
+ void *actarg);
+ int get_subcontainers_of_container(struct query *q, char **argv, client *cl,
+ int (*action)(int, char *[], void *),
+ void *actarg);
+
/* prototypes from qvalidate.pc */
int validate_fields(struct query *q, char *argv[], struct valobj *vo, int
n);
Index: qsupport.pc
===================================================================
RCS file:
\\dongq-afs\all\athena.mit.edu\astaff\project\moiradev\repository/moira/serv
er/qsupport.pc,v
retrieving revision 2.32
diff -c -r2.32 qsupport.pc
*** qsupport.pc 2001/04/01 05:31:20 2.32
--- qsupport.pc 2001/04/24 15:08:39
***************
*** 1851,1853 ****
--- 1851,2073 ----
return MR_SUCCESS;
}
+
+ int update_container(struct query *q, char *argv[], client *cl)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ int cnt_id, acl_id, memacl_id, who;
+ char cname[CONTAINERS_CNAME_SIZE], newchildcname[CONTAINERS_CNAME_SIZE];
+ char* newcname, *entity, *description, *location, *contact, *acl_type,
*memacl_type;
+ EXEC SQL END DECLARE SECTION;
+ char* tmpchar;
+ int cnt, childid;
+ char childcname[CONTAINERS_CNAME_SIZE];
+
+ cnt_id = *(int *)argv[0];
+ newcname = argv[1];
+ description = argv[2];
+ location = argv[3];
+ contact = argv[4];
+ acl_type = argv[5];
+ acl_id = *(int *)argv[6];
+ memacl_type = argv[7];
+ memacl_id = *(int *)argv[8];
+ entity = cl->entity;
+ who = cl->client_id;
+
+ EXEC SQL SELECT cname INTO :cname
+ FROM containers
+ WHERE cnt_id = :cnt_id;
+
+ /* if we are renaming the container */
+ if (strcmp(cname, newcname))
+ {
+ /* make sure that only the name part of the cname has been changed */
+ tmpchar = strrchr(cname, '/');
+ /* not a top-level name */
+ if (tmpchar)
+ {
+ cnt = tmpchar - cname + 1;
+ /* the parent part of the old and new name should be identical */
+ if (strncmp(cname, newcname, cnt))
+ return MR_NEW_CONTAINER_NAME;
+ }
+ /* top level name, new name should be a top level name too */
+ else
+ {
+ if (strrchr(newcname, '/'))
+ return MR_NEW_CONTAINER_NAME;
+ }
+
+ /* update the cname for this container */
+ EXEC SQL UPDATE containers
+ SET cname = :newcname
+ WHERE cnt_id = :cnt_id;
+
+ if (dbms_errno)
+ return mr_errcode;
+
+ /* get cnames for its child containers */
+ EXEC SQL DECLARE csr_ucon CURSOR FOR
+ SELECT cname, cnt_id FROM container WHERE cname LIKE :cname || '/'
|| '%';
+
+ EXEC SQL OPEN csr_ucon;
+ if (dbms_errno)
+ return mr_errcode;
+
+ while (1)
+ {
+ EXEC SQL FETCH csr_ucon INTO :childcname, :childid;
+ if (sqlca.sqlcode)
+ break;
+
+ /* concatenate the new parent cname with the existing sub-container
name
+ * we get the sub-containers new cname */
+ tmpchar = childcname + strlen(cname);
+ strcpy(newchildcname, newcname);
+ strcat(newchildcname, tmpchar);
+
+ /* update the cname */
+ EXEC SQL UPDATE containers
+ SET cname = :newchildcname, modtime = SYSDATE, modby = :who,
modwith = :entity
+ WHERE cnt_id = :childid;
+
+ if (sqlca.sqlcode)
+ break;
+ }
+
+ EXEC SQL CLOSE csr_gubr;
+ if (dbms_errno)
+ return mr_errcode;
+ }
+
+ /* update the remaining fields */
+ EXEC SQL UPDATE containers
+ SET description = NVL(:description, CHR(0)), location =
NVL(:location, CHR(0)),
+ contact = NVL(:contact, CHR(0)), acl_type = :acl_type, acl_id =
:acl_id,
+ memacl_type = :memacl_type, memacl_id = :memacl_id,
+ modtime = SYSDATE, modby = :who, modwith = :entity
+ WHERE cnt_id = :cnt_id;
+
+ if (dbms_errno)
+ return mr_errcode;
+
+ return MR_SUCCESS;
+ }
+
+ int get_machines_of_container(struct query *q, char *argv[], client *cl,
+ int (*action)(int, char *[], void *), void *actarg)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ int cnt_id, isrecursive;
+ char machinename[MACHINE_NAME_SIZE],
containercname[CONTAINERS_CNAME_SIZE];
+ char *qs;
+ EXEC SQL END DECLARE SECTION;
+
+ char querystring[512], tmp [256];
+ char *rargv[2];
+ int found = 0;
+
+ rargv[0] = machinename;
+ rargv[1] = containercname;
+
+ cnt_id = *(int *)argv[0];
+ isrecursive = *(int *)argv[1];
+
+ /* get the container name */
+
+ EXEC SQL SELECT cname INTO :containercname
+ FROM containers
+ WHERE cnt_id = :cnt_id;
+
+ strcpy(querystring, "SELECT a.name, b.cname FROM machine a, containers
b, mcntmap c ");
+ strcat(querystring, "WHERE a.mach_id = c.mach_id AND b.cnt_id =
c.cnt_id ");
+
+ if (!isrecursive)
+ sprintf(tmp, "AND b.cnt_id = %d ", cnt_id);
+ else
+ sprintf(tmp, "AND (b.cnt_id = %d OR b.cname LIKE '%s/%%') ", cnt_id,
containercname);
+
+ strcat(querystring, tmp);
+ strcat(querystring, "ORDER BY b.cname, a.name");
+
+ qs = querystring;
+
+ EXEC SQL PREPARE stmt FROM :qs;
+ if (sqlca.sqlcode)
+ return MR_INTERNAL;
+ EXEC SQL DECLARE curs_gmnm CURSOR FOR stmt;
+ EXEC SQL OPEN curs_gmnm;
+
+ while (1)
+ {
+ EXEC SQL FETCH curs_gmnm INTO :machinename, :containercname;
+ if (sqlca.sqlcode)
+ break;
+ (*action)(2, rargv, actarg);
+ found++;
+ }
+
+ EXEC SQL CLOSE curs_gmnm;
+ if (!found)
+ return MR_NO_MATCH;
+ return MR_SUCCESS;
+ }
+
+ int get_subcontainers_of_container(struct query *q, char *argv[], client
*cl,
+ int (*action)(int, char *[], void *), void *actarg)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ int cnt_id, isrecursive;
+ char containercname[CONTAINERS_CNAME_SIZE],
subcontainercname[CONTAINERS_CNAME_SIZE];
+ char *qs;
+ EXEC SQL END DECLARE SECTION;
+
+ char querystring[512], tmp [256];
+ char *rargv[1];
+ int found = 0;
+
+ rargv[0] = subcontainercname;
+
+ cnt_id = *(int *)argv[0];
+ isrecursive = *(int *)argv[1];
+
+ /* get the container name */
+
+ EXEC SQL SELECT cname INTO :containercname
+ FROM containers
+ WHERE cnt_id = :cnt_id;
+
+ strcpy(querystring, "SELECT cname FROM containers ");
+
+ if (!isrecursive)
+ sprintf(tmp, "WHERE cname LIKE '%s/%%' and cname NOT LIKE '%s/%%/%%'
", containercname,
+ containercname);
+ else
+ sprintf(tmp, "WHERE cname LIKE '%s/%%' ", containercname);
+
+ strcat(querystring, tmp);
+ strcat(querystring, "ORDER BY cname");
+
+ qs = querystring;
+
+ EXEC SQL PREPARE stmt FROM :qs;
+ if (sqlca.sqlcode)
+ return MR_INTERNAL;
+ EXEC SQL DECLARE curs_gsoc CURSOR FOR stmt;
+ EXEC SQL OPEN curs_gsoc;
+
+ while (1)
+ {
+ EXEC SQL FETCH curs_gsoc INTO :subcontainercname;
+ if (sqlca.sqlcode)
+ break;
+ (*action)(1, rargv, actarg);
+ found++;
+ }
+
+ EXEC SQL CLOSE curs_gsoc;
+ if (!found)
+ return MR_NO_MATCH;
+ return MR_SUCCESS;
+ }
Index: qsetup.pc
===================================================================
RCS file:
\\dongq-afs\all\athena.mit.edu\astaff\project\moiradev\repository/moira/serv
er/qsetup.pc,v
retrieving revision 2.42
diff -c -r2.42 qsetup.pc
*** qsetup.pc 2000/12/19 07:32:46 2.42
--- qsetup.pc 2001/04/24 15:18:35
***************
*** 222,227 ****
--- 222,231 ----
EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
if (dbms_errno)
return mr_errcode;
+
+ EXEC SQL DELETE FROM mcntmap WHERE mach_id = :id;
+ if (dbms_errno)
+ return mr_errcode;
return MR_SUCCESS;
}
***************
*** 1254,1259 ****
--- 1258,1296 ----
if (cnt > 0)
return MR_IN_USE;
+ return MR_SUCCESS;
+ }
+
+ int setup_dcon(struct query *q, char *argv[], client *cl)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ int id, cnt;
+ char containercname[CONTAINERS_CNAME_SIZE];
+ EXEC SQL END DECLARE SECTION;
+
+ id = *(int *)argv[0];
+ /* check to see if there are machines in this container */
+ EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcntmap
+ WHERE cnt_id = :id;
+ if (cnt > 0)
+ return MR_IN_USE;
+
+ /* check to see if there are subcontainers in this container */
+
+ /* get the container name */
+
+ EXEC SQL SELECT cname INTO :containercname
+ FROM containers
+ WHERE cnt_id = :id;
+
+ EXEC SQL SELECT COUNT(cnt_id) INTO :cnt FROM containers
+ WHERE cname LIKE :containercname || '/' || '%';
+
+ if (cnt > 0)
+ return MR_IN_USE;
+
+ if (dbms_errno)
+ return mr_errcode;
return MR_SUCCESS;
}
Index: queries2.c
===================================================================
RCS file:
\\dongq-afs\all\athena.mit.edu\astaff\project\moiradev\repository/moira/serv
er/queries2.c,v
retrieving revision 2.82
diff -c -r2.82 queries2.c
*** queries2.c 2000/12/19 07:32:47 2.82
--- queries2.c 2001/04/24 15:19:02
***************
*** 42,47 ****
--- 42,51 ----
{V_ID, 0, FILESYS_TABLE, "label", "filsys_id", MR_FILESYS},
};
+ static struct valobj VOcon0[] = {
+ {V_ID, 0, CONTAINERS_TABLE, "cname", "cnt_id", MR_CONTAINER},
+ };
+
static struct valobj VOnum0[] = {
{V_NUM, 0},
};
***************
*** 3107,3114 ****
static char *gdds_fields[] = {
"sid",
};
-
/* Generalized Query Definitions */
/* Multiple versions of the same query MUST be listed in ascending
--- 3111,3274 ----
static char *gdds_fields[] = {
"sid",
};
+
+ static char *gcon_fields[] = {
+ "cname",
+ "cname", "description", "location", "contact",
+ "ace_type", "ace_name", "memace_type", "memace_name", "modtime",
"modby", "modwith",
+ };
+
+ static struct validate gcon_validate = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ followup_gcon,
+ };
+
+ static char *acon_fields[] = {
+ "cname", "description", "location", "contact",
+ "ace_type", "ace_name", "memace_type", "memace_name",
+ };
+
+ static struct valobj acon_valobj[] = {
+ {V_CHAR, 0, CONTAINERS_TABLE, "cname"},
+ {V_LEN, 1, CONTAINERS_TABLE, "description"},
+ {V_CHAR, 2, CONTAINERS_TABLE, "location"},
+ {V_CHAR, 3, CONTAINERS_TABLE, "contact"},
+ {V_TYPE, 4, 0, "ace_type", 0, MR_ACE},
+ {V_TYPEDATA, 5, 0, 0, 0, MR_ACE},
+ {V_TYPE, 6, 0, "ace_type", 0, MR_ACE},
+ {V_TYPEDATA, 7, 0, 0, 0, MR_ACE},
+ };
+
+ static struct validate acon_validate =
+ {
+ acon_valobj,
+ 8,
+ "cname",
+ "cname = '%s'",
+ 1,
+ "cnt_id",
+ 0,
+ prefetch_value,
+ set_modtime,
+ };
+
+ static char *ucon_fields[] = {
+ "cname",
+ "newcname", "description", "location", "contact",
+ "ace_type", "ace_name", "memace_type", "memace_name",
+ };
+
+ static struct valobj ucon_valobj[] = {
+ {V_ID, 0, CONTAINERS_TABLE, "cname", "cnt_id", MR_CONTAINER},
+ {V_RENAME, 1, CONTAINERS_TABLE, "cname", "cnt_id", MR_NOT_UNIQUE},
+ {V_LEN, 2, CONTAINERS_TABLE, "description"},
+ {V_CHAR, 3, CONTAINERS_TABLE, "location"},
+ {V_CHAR, 4, CONTAINERS_TABLE, "contact"},
+ {V_TYPE, 5, 0, "ace_type", 0, MR_ACE},
+ {V_TYPEDATA, 6, 0, 0, 0, MR_ACE},
+ {V_TYPE, 7, 0, "ace_type", 0, MR_ACE},
+ {V_TYPEDATA, 8, 0, 0, 0, MR_ACE},
+ };
+
+ static struct validate ucon_validate =
+ {
+ ucon_valobj,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ access_container,
+ 0,
+ update_container,
+ };
+
+ static char *dcon_fields[] = {
+ "cname",
+ };
+
+ static struct validate dcon_validate =
+ {
+ VOcon0,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ setup_dcon,
+ 0,
+ };
+
+ static char *amcn_fields[] = {
+ "machine", "container",
+ };
+
+ static struct valobj amcn_valobj[] = /* ADD_MACHINE_TO_CONTAINER */
+ { /* DELETE_MACHINE_FROM_CONTAINER */
+ {V_ID, 0, MACHINE_TABLE, "name", "mach_id", MR_MACHINE},
+ {V_ID, 1, CONTAINERS_TABLE, "cname", "cnt_id", MR_CONTAINER},
+ };
+
+ static struct validate amcn_validate = /* for amtn and dmfn */
+ {
+ amcn_valobj,
+ 2,
+ "mach_id",
+ "mach_id = %d and cnt_id = %d",
+ 2,
+ 0,
+ access_container,
+ 0,
+ set_mach_modtime_by_id,
+ };
+
+ static char *gmoc_fields[] = {
+ "container",
+ "isrecursive",
+ "machine",
+ "container",
+ };
+
+ static struct validate gmoc_validate =
+ {
+ VOcon0,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ get_machines_of_container,
+ };
+
+ static char *gsoc_fields[] = {
+ "container",
+ "isrecursive",
+ "subcontainer",
+ };
+
+ static struct validate gsoc_validate =
+ {
+ VOcon0,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ get_subcontainers_of_container,
+ };
/* Generalized Query Definitions */
/* Multiple versions of the same query MUST be listed in ascending
***************
*** 6424,6429 ****
--- 6584,6742 ----
0,
NULL,
NULL,
+ },
+
+ {
+ /* Q_GCON - GET_CONTAINER, v7 */
+ "get_container",
+ "gcon",
+ 7,
+ RETRIEVE,
+ "c",
+ CONTAINERS_TABLE,
+ "cname, description, location, contact, acl_type, acl_id,
memacl_type, memacl_id, TO_CHAR(modtime, 'DD-mon-YYYY HH24:MI:SS'), modby,
modwith FROM containers",
+ gcon_fields,
+ 11,
+ "cname = '%s' AND cnt_id != 0",
+ 1,
+ NULL,
+ &gcon_validate,
+ },
+
+ {
+ /* Q_ACON - ADD_CONTAINER, v7 */ /* uses prefetch_value() for cnt_id */
+ "add_container",
+ "acon",
+ 7,
+ APPEND,
+ "c",
+ CONTAINERS_TABLE,
+ "INTO containers (cname, description, location, contact, acl_type,
acl_id, memacl_type, memacl_id, cnt_id) VALUES ('%s', NVL('%s', CHR(0)),
NVL('%s', CHR(0)), NVL('%s', CHR(0)), '%s', %d, '%s', %d, %s)",
+ acon_fields,
+ 8,
+ 0,
+ 0,
+ NULL,
+ &acon_validate,
+ },
+
+ {
+ /* Q_UCON - UPDATE_CONTAINER, v7 */
+ "update_container",
+ "ucon",
+ 7,
+ UPDATE,
+ 0,
+ CONTAINERS_TABLE,
+ 0,
+ ucon_fields,
+ 8,
+ 0,
+ 0,
+ NULL,
+ &ucon_validate,
+ },
+
+ {
+ /* Q_DCON - DELETE_CONTAINER, v7 */
+ "delete_container",
+ "dcon",
+ 7,
+ DELETE,
+ "c",
+ CONTAINERS_TABLE,
+ NULL,
+ dcon_fields,
+ 0,
+ "cnt_id = %d",
+ 1,
+ NULL,
+ &dcon_validate,
+ },
+
+ {
+ /* Q_AMCN - ADD_MACHINE_TO_CONTAINER, v7 */
+ "add_machine_to_container",
+ "amcn",
+ 7,
+ APPEND,
+ "mcn",
+ MCNTMAP_TABLE,
+ "INTO mcntmap (mach_id, cnt_id) VALUES (%d, %d)",
+ amcn_fields,
+ 2,
+ 0,
+ 0,
+ NULL,
+ &amcn_validate,
+ },
+
+ {
+ /* Q_DMCN - DELETE_MACHINE_FROM_CONTAINER, v7 */
+ "delete_machine_from_container",
+ "dmcn",
+ 7,
+ DELETE,
+ "mcn",
+ MCNTMAP_TABLE,
+ 0,
+ amcn_fields,
+ 0,
+ "mach_id = %d AND cnt_id = %d",
+ 2,
+ NULL,
+ &amcn_validate,
+ },
+
+ {
+ /* Q_GMNM - GET_MACHINE_TO_CONTAINER_MAP, v7 */
+ "get_machine_to_container_map",
+ "gmnm",
+ 7,
+ RETRIEVE,
+ "mcn",
+ MCNTMAP_TABLE,
+ "c.cname FROM machine m, containers c, mcntmap mcn",
+ amcn_fields,
+ 1,
+ "m.name = UPPER('%s') AND mcn.cnt_id = c.cnt_id AND mcn.mach_id =
m.mach_id",
+ 1,
+ NULL,
+ NULL,
+ },
+
+ {
+ /* Q_GMOC - GET_MACHINES_OF_CONTAINER, v7 */
+ "get_machines_of_container",
+ "gmoc",
+ 7,
+ RETRIEVE,
+ NULL,
+ MCNTMAP_TABLE,
+ NULL,
+ gmoc_fields,
+ 2,
+ NULL,
+ 0,
+ NULL,
+ &gmoc_validate,
+ },
+
+ {
+ /* Q_GSOC - GET_SUBCONTAINERS_OF_CONTAINER, v7 */
+ "get_subcontainers_of_container",
+ "gsoc",
+ 7,
+ RETRIEVE,
+ NULL,
+ CONTAINERS_TABLE,
+ NULL,
+ gsoc_fields,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &gsoc_validate,
},
};
At 01:00 AM 4/24/2001 -0400, Garry Zacheiss wrote:
> Hi Qing,
>
> A read through this looks good. I'd like to ask for one
>behavior change, though; currently, as you have things implemented,
>deleting a container will remove all the machines from the container
>without prompting and then delete the container. This seems like it
>could be a nasty user interface if someone typos a name. I'd much
>rather see the query return MR_IN_USE if there are machines still in a
>container, and only allow you to delete empty containers. This is how
>the deletion of cluster is currently handled. In the "moira" client, we
>check if the query returned MR_IN_USE, and display a list of all the
>machines in the cluster, and then ask the user if they'd like to remove
>them all and then proceed. I'd like to see similar behavior for the
>delete_container operation.
>
>Garry
>