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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <sys/types.h>
32 #include <sys/mnttab.h>
50 #include <sys/nsctl/cfg_impl.h>
51 #include <sys/nsctl/cfg.h>
53 #include <sys/unistat/spcs_s.h>
54 #include <sys/unistat/spcs_s_u.h>
55 #include <sys/unistat/spcs_errors.h>
58 #include <sys/nsctl/dsw.h>
61 #define DEFAULT_PARSER_LOC "/etc/dscfg_format"
79 char *locname
; /* config location from cfg_location */
82 #define MAX_FILENAME 80
84 char output_file
[MAX_FILENAME
]; /* specified output file */
85 char altroot
[MAX_FILENAME
]; /* specifed root location */
86 char config_file
[MAX_FILENAME
]; /* specified configuration file */
87 char input_file
[MAX_FILENAME
]; /* specified input file */
88 char logical_host
[MAX_FILENAME
]; /* specified cluster node */
89 char device_group
[MAX_FILENAME
]; /* specified device group name */
91 #define IS_NOT_CLUSTER 1
94 void cfg_invalidate_hsizes(int, const char *);
95 static int check_cluster();
101 (void) fprintf(stderr
, "%s: %s\n", cmdname
, errmsg
);
102 (void) fprintf(stderr
,
103 gettext("dscfg \t\t\t\tDisplay location of "
104 "local configuration database\n"));
105 (void) fprintf(stderr
, gettext("dscfg -l -s path\t\t"
106 "List contents of configuration database\n"));
107 (void) fprintf(stderr
, gettext(
108 "\t\t\t\tlocated at path specified\n"));
109 (void) fprintf(stderr
, gettext("dscfg -i\t\t\t"
110 "Initialize configuration database\n"));
111 (void) fprintf(stderr
,
112 gettext("dscfg -i -p "
116 "/etc/dscfg_format\tFormat configuration database\n"));
117 (void) fprintf(stderr
,
118 gettext("dscfg -a file\t\t\tRestore configuration "
119 "database from file\n"));
120 (void) fprintf(stderr
, gettext("\t\t\t\tspecified\n"));
121 (void) fprintf(stderr
,
122 gettext("dscfg -l\t\t\tList contents of configuration database"
124 (void) fprintf(stderr
,
125 gettext("dscfg -L\t\t\tDisplay configuration database's\n"));
126 (void) fprintf(stderr
, gettext("\t\t\t\tlock status\n"));
127 (void) fprintf(stderr
, gettext("dscfg -h\t\t\tUsage message\n"));
128 if (check_cluster() != IS_NOT_CLUSTER
) {
129 (void) fprintf(stderr
, gettext("\nSun Cluster Usage\n"));
130 (void) fprintf(stderr
, gettext("******************\n"));
131 (void) fprintf(stderr
,
132 gettext("dscfg -s path\t\t\tSet cluster "
133 "configuration database at DID\n"));
134 (void) fprintf(stderr
, gettext("\t\t\t\tpath specified\n"));
135 (void) fprintf(stderr
, gettext("dscfg -D device_group\t\t"
136 "Check status of cluster device group\n"));
137 (void) fprintf(stderr
, gettext("dscfg -C -\t\t\t"
138 "Display location of cluster configuration\n"));
139 (void) fprintf(stderr
, gettext("\t\t\t\tdatabase\n"));
140 (void) fprintf(stderr
, gettext("dscfg -l -s DID_device\t\tList "
141 "the contents of cluster configuration\n"));
142 (void) fprintf(stderr
, gettext("\t\t\t\tdatabase\n"));
143 (void) fprintf(stderr
, gettext("dscfg -C - -i\t\t\tInitialize "
144 "cluster configuration database\n"));
145 (void) fprintf(stderr
, gettext("dscfg -C - -i -p "
146 "/etc/dscfg_format Format cluster configuration database\n"));
147 (void) fprintf(stderr
, gettext("dscfg -C - -a file\t\t"
148 "Restore cluster configuration database from\n"));
149 (void) fprintf(stderr
, gettext("\t\t\t\tfile specified\n"));
150 (void) fprintf(stderr
, gettext("dscfg -C - -l\t\t\t"
151 "List contents of local configuration database\n"));
152 (void) fprintf(stderr
, gettext("dscfg -C device_group -l\t"
153 "List configuration database by device group\n"));
154 (void) fprintf(stderr
, gettext("dscfg -C \"-\" -l\t\t\t"
155 "List configuration database excluding\n"));
156 (void) fprintf(stderr
, gettext("\t\t\t\tdevice groups\n"));
161 parse_parse_config(CFGFILE
*cfg
)
164 char inbuf
[CFG_MAX_BUF
];
169 * Open parser config file, use default if none specified
171 buff
= (input_file
[0]) ? input_file
: DEFAULT_PARSER_LOC
;
172 if ((fp
= fopen(buff
, "r")) == NULL
) {
173 (void) fprintf(stderr
,
174 gettext("parser config file (%s) not found\n"), buff
);
179 * start at begining of configration database
181 cfg_rewind(cfg
, CFG_SEC_ALL
);
183 while (((buff
= fgets(inbuf
, (sizeof (inbuf
) - 1), fp
)) != NULL
)) {
184 if (*buff
== '#' || *buff
== '%')
186 /* overwrite newline */
187 buff
[strlen(buff
) - 1] = '\0';
188 rc
= cfg_update_parser_config(cfg
, buff
, CFG_PARSE_CONF
);
190 (void) fprintf(stderr
,
191 gettext("update parser config rc %d key %s\n"),
202 parse_text_config(CFGFILE
*cfg
)
205 char inbuf
[CFG_MAX_BUF
];
211 if ((fp
= fopen(input_file
, "r")) == NULL
) {
212 (void) fprintf(stderr
,
213 gettext("Unable to open text config %s\n"),
217 bzero(inbuf
, sizeof (inbuf
));
218 cfg_rewind(cfg
, CFG_SEC_CONF
);
219 while (((buff
= fgets(inbuf
, (sizeof (inbuf
) - 1), fp
)) != NULL
)) {
222 /* overwrite newline */
223 buff
[strlen(buff
) - 1] = '\0';
224 key
= strtok(buff
, ":");
228 p
= &buff
[strlen(key
)+2];
229 while (*p
&& isspace(*p
)) {
235 rc
= cfg_put_cstring(cfg
, key
, p
, strlen(p
));
237 (void) fprintf(stderr
,
238 gettext("update text config failed rc %d key %s"),
242 bzero(inbuf
, sizeof (inbuf
));
247 dump_status(CFGFILE
*cfg
)
249 cfp_t
*cfp
= FP_SUN_CLUSTER(cfg
);
252 * WARNING will robinson
253 * The following is using a non-exported internal interface
255 * You may not use any of the following fields in MS software
260 (void) printf("%s\n", locname
);
263 (void) printf(gettext("Configuration location: %s\n"), locname
);
265 gettext("Header info:\n\t\t\tmagic: %x\tstate: %x\n"),
266 cfp
->cf_head
->h_magic
, cfp
->cf_head
->h_state
);
268 gettext("Parser section:\t\t"
269 "Start: %x\tsize: %d offset: %d\n"),
270 cfp
->cf_mapped
, cfp
->cf_head
->h_parsesize
,
271 cfp
->cf_head
->h_parseoff
);
273 gettext("Config section:\t\t"
274 "Start: %x\tsize:%d\tacsize: %d\n"),
275 cfp
->cf_head
->h_cparse
, cfp
->cf_head
->h_csize
,
276 cfp
->cf_head
->h_acsize
);
277 (void) printf("\t\t\tccopy1: %s\tccopy2: %s\n",
278 cfp
->cf_head
->h_ccopy1
,
279 cfp
->cf_head
->h_ccopy2
);
281 gettext("Sequence:\t\tseq1: %d\t\tseq2: %d\n"),
282 cfp
->cf_head
->h_seq1
, cfp
->cf_head
->h_seq2
);
288 dump_lockstat(CFGFILE
*cfg
)
294 if (cfg_get_lock(cfg
, &lock
, &pid
) == TRUE
) {
295 (void) printf("%s %ld\n",
297 gettext("Read locked by process id") :
298 gettext("Write locked by process id"),
300 (void) sprintf(ps_str
, "ps -p %ld", pid
);
303 (void) printf("%s\n", gettext("Not locked."));
308 * dump current configuration section to stdout
312 print_config(CFGFILE
*cfg
)
316 char pconfig
[CFG_MAX_BUF
];
317 char key
[CFG_MAX_KEY
];
318 char buf
[CFG_MAX_BUF
];
319 char *cp
, pbuf
[CFG_MAX_BUF
];
324 (void) snprintf(pconfig
, sizeof (pconfig
),
325 "%s%s", altroot
, DEFAULT_PARSER_LOC
);
326 if ((fp
= fopen(pconfig
, "r")) == NULL
) {
327 (void) fprintf(stderr
,
328 gettext("dscfg: unable to open "
329 "parser configuration (%s): %s\n"),
330 pconfig
, strerror(errno
));
335 (void) printf(gettext("# Consolidated Dataservice Configuration\n"));
336 (void) printf(gettext("# Do not edit out whitespace or dashes\n"));
337 (void) printf(gettext("# File created on: %s"), ctime(&tloc
));
339 while (fgets(pbuf
, (sizeof (pbuf
) - 1), fp
) != NULL
) {
340 if (pbuf
[0] == '#') {
344 /* force a NULL terminator */
345 pbuf
[sizeof (pbuf
) - 1] = '\0';
347 if (pbuf
[0] == '%') {
350 * - print it (with comment leader) and move on
352 (void) printf("#%s", &pbuf
[1]);
357 * truncate the parser config in pbuf[] to just the tag
359 cp
= strchr(pbuf
, '.');
367 bzero(buf
, CFG_MAX_BUF
);
369 sizeof (key
), "%s.set%d", pbuf
, set
);
370 rc
= cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
);
374 /* trim trailing space if necessary */
375 end
= strlen(buf
) - 1;
379 (void) printf("%s:%s\n", pbuf
, buf
);
388 make_new_config(const char *fileloc
)
394 char buf
[CFG_MAX_BUF
];
396 assert((sizeof (buf
) % 512) == 0);
398 bzero(buf
, CFG_MAX_BUF
);
400 if ((fd
= open(fileloc
, O_RDWR
| O_CREAT
, 0640)) == -1) {
404 /* if this is a device, we may have to skip the vtoc */
405 if ((skip
= cfg_shldskip_vtoc(fd
, fileloc
)) == -1) {
406 (void) fprintf(stderr
,
407 gettext("dscfg: unable to read vtoc on (%s)\n"),
412 rc
= lseek(fd
, CFG_VTOC_SKIP
, SEEK_SET
);
413 } while (rc
== -1 && errno
== EINTR
);
416 (void) fprintf(stderr
, gettext("dscfg: seek error"));
422 rc
= write(fd
, buf
, sizeof (buf
));
423 } while (rc
== -1 && errno
== EINTR
);
427 return ((rc
< 0) ? 0 : 1);
432 * configure or return dataservice persistent configuration
435 * -i initialize file for first time
436 * -l dump current configuration to stdout in ascii
438 * -C node Set resource filter
439 * -p parser config specified input file
440 * -s set partition location or filename in default location
441 * -L print configuration lock status
443 * -r prepend bootdir to beginning of path for cfg_open
450 dscfg_lintmain(int argc
, char *argv
[])
453 main(int argc
, char *argv
[])
463 int action_counts
= 0;
465 bzero(input_file
, sizeof (input_file
));
466 (void) setlocale(LC_ALL
, "");
467 (void) textdomain("dscfg");
468 logical_host
[0] = '\0';
471 while ((c
= getopt(argc
, argv
, "a:C:dD:ilLp:r:s:hvn")) != EOF
) {
473 while ((c
= getopt(argc
, argv
, "a:C:dD:ilLp:r:s:h")) != EOF
) {
478 strcpy(input_file
, optarg
);
484 strcpy(logical_host
, optarg
);
485 if (logical_host
&& *logical_host
== '-')
491 strcpy(device_group
, optarg
);
509 strcpy(input_file
, optarg
);
514 strcpy(config_file
, optarg
);
536 strcpy(altroot
, optarg
);
550 switch (action_counts
) {
555 "-p option must be used in conjunction with -i"));
557 usage(gettext("must specify an action flag"));
567 usage(gettext("too many action flags"));
572 usage(gettext("too many action flags"));
577 if (argc
== 1 || (argc
== 2 && verbose
) || (argc
== 3 && (rflg
|Cflg
)))
582 * Determine if the value specified is a device group
583 * that is active on this node
586 if ((cfg_issuncluster() > 0) && (strlen(device_group
) > 0)) {
587 local
= cfg_dgname_islocal(device_group
, &other_node
);
589 (void) fprintf(stderr
, gettext(
590 "Device group %s active on %s\n"),
591 device_group
, other_node
);
593 (void) fprintf(stderr
, gettext(
594 "Device group %s active on this node\n"),
597 (void) fprintf(stderr
, gettext(
598 "Device group %s not found\n"), device_group
);
601 (void) fprintf(stderr
, gettext(
602 "dscfg -D is only allowed in "
603 "Sun Cluster OE\n"));
610 * Only allow setting location on a non-sun cluster system
611 * if the cluster reference file is already present.
613 struct stat dscfg_stat
= {0};
614 if (cfg_issuncluster() <= 0) {
615 if (stat(CFG_CLUSTER_LOCATION
, &dscfg_stat
) != 0) {
616 if (dscfg_stat
.st_blocks
== 0) {
617 (void) fprintf(stderr
, gettext(
618 "dscfg -s is only allowed in "
619 "Sun Cluster OE\n"));
625 spcs_log("dscfg", NULL
, gettext("dscfg -s %s"), config_file
);
626 locname
= cfg_location(config_file
, CFG_LOC_SET_CLUSTER
,
627 rflg
? altroot
: NULL
);
628 if (locname
== NULL
) {
629 (void) fprintf(stderr
, gettext("dscfg: %s\n"),
635 } else if (sflg
&& lflg
) {
636 /* s used with l for temporarily peeking at a dscfg database */
639 locname
= cfg_location(NULL
,
640 Cflg
? CFG_LOC_GET_CLUSTER
: CFG_LOC_GET_LOCAL
,
641 rflg
? altroot
: NULL
);
642 if (Cflg
&& (locname
== NULL
)) {
643 (void) fprintf(stderr
, gettext(
644 "dscfg: cluster config not set: %s\n"),
648 loc
= rflg
? locname
: NULL
;
652 * the following hack forces the configuration file to initialize
657 char buf
[CFG_MAX_BUF
] = {0};
662 gettext("WARNING: This option will erase your "
663 "Availability Suite configuration\n"));
665 gettext("Do you want to continue? (Y/N) [N] "));
674 (void) fprintf(stderr
, gettext(
675 "dscfg: configuration not initialized\n"));
678 (void) fprintf(stderr
, gettext(
679 "dscfg: %d is not a valid response\n"), c
);
684 spcs_log("dscfg", NULL
, gettext("dscfg -i"));
686 if ((cfg
= cfg_open(loc
)) == NULL
) {
687 /* this is not a good config, or non-existent so.. */
688 if (!make_new_config(locname
)) {
689 (void) fprintf(stderr
, gettext("dscfg: %s\n"),
693 if ((cfg
= cfg_open(loc
)) == NULL
) {
694 (void) fprintf(stderr
, gettext("dscfg: %s\n"),
701 * Set cluster node if specified
704 cfg_resource(cfg
, logical_host
);
706 if (cfg_is_cfg(cfg
) != 1) {
707 if (!make_new_config(locname
)) {
708 (void) fprintf(stderr
, gettext("dscfg: unable "
709 " to create new config \n"));
714 if (!cfg_lock(cfg
, CFG_WRLOCK
)) {
715 (void) fprintf(stderr
, gettext("dscfg: %s\n"),
720 cfp
= FP_SUN_CLUSTER(cfg
);
721 if ((fild
= cfp
->cf_fd
) == 0) {
722 (void) fprintf(stderr
,
723 gettext("dscfg: failure to access %s "
724 "configuration database: %s\n"),
725 (Cflg
) ? gettext("cluster") : gettext("local"),
730 if (cfg_shldskip_vtoc(fild
, locname
) > 0)
731 offset
+= CFG_VTOC_SKIP
;
733 lseek(fild
, offset
, SEEK_SET
);
734 write(fild
, buf
, sizeof (buf
));
735 cfg_invalidate_hsizes(fild
, locname
);
742 usage(gettext("-p option must be used in conjunction with -i"));
748 char cmd
[CFG_MAX_BUF
];
750 (void) snprintf(cmd
, sizeof (cmd
),
751 "%s/usr/sbin/dscfg -r %s -l >"
752 " %s/var/tmp/.dscfg.bak", altroot
,
755 (void) snprintf(cmd
, sizeof (cmd
),
756 "/usr/sbin/dscfg -l >"
757 " /var/tmp/.dscfg.bak");
759 if (system(cmd
) != 0) {
760 (void) fprintf(stderr
,
761 "dscfg: unable to create backup\n");
765 if ((cfg
= cfg_open(loc
)) == NULL
) {
766 (void) fprintf(stderr
, gettext("dscfg: %s\n"),
771 if (!cfg_lock(cfg
, CFG_UPGRADE
)) {
772 (void) fprintf(stderr
,
773 gettext("dscfg: upgrade failed\n"));
782 if ((cfg
= cfg_open(loc
)) == NULL
) {
783 (void) fprintf(stderr
, gettext("dscfg: %s\n"), cfg_error(NULL
));
788 * Set cluster node if specified
791 cfg_resource(cfg
, logical_host
);
793 if ((!pflg
) && (!noflags
)) {
794 if (cfg_is_cfg(cfg
) != 1) {
795 (void) fprintf(stderr
,
796 gettext("dscfg: %s\n"), cfg_error(NULL
));
814 if (!cfg_lock(cfg
, mustcommit
? CFG_WRLOCK
: CFG_RDLOCK
)) {
815 (void) fprintf(stderr
, gettext("cfg_lock: lock failed\n"));
827 * initialize configuration
830 spcs_log("dscfg", NULL
, gettext("dscfg -i -p %s"), input_file
);
833 (void) fprintf(stderr
,
834 gettext("dscfg: cannot init without "
835 "parser configuration file\n"));
838 } else if (parse_parse_config(cfg
) < 0) {
839 (void) fprintf(stderr
, gettext("dscfg: cannot load "
840 "parser configuration file\n"));
847 * read asci config file and write
850 spcs_log("dscfg", NULL
, gettext("dscfg -a %s"), input_file
);
851 parse_text_config(cfg
);
855 rc
= cfg_commit(cfg
);
858 (void) fprintf(stderr
, gettext("dscfg: %s\n"),
860 if (sev
== CFG_EFATAL
) {
874 static int is_cluster
= -1;
877 if (is_cluster
!= -1)
879 rc
= cfg_iscluster();
881 is_cluster
= IS_CLUSTER
;
883 } else if (rc
== 0) {
884 is_cluster
= IS_NOT_CLUSTER
;
887 (void) fprintf(stderr
,
888 gettext("dscfg: unable to determin environment\n"));