/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* Metadevice diskset utility.
*/
#include <meta.h>
#include <sdssc.h>
enum metaset_cmd {
add,
take,
};
enum cluster_cmd {
};
static void
char *string)
{
"usage:\t%s -s setname -a [-A enable | disable] -h hostname ...\n"
" %s -s setname -a [-M] -h hostname ...\n"
" %s -s setname -a [-M] [-l length] [-L] drivename ...\n"
" %s -s setname -d [-M] -h hostname ...\n"
" %s -s setname -d [-M] -f -h all-hostnames\n"
" %s -s setname -d [-M] [-f] drivename ...\n"
" %s -s setname -d [-M] [-f] hostname ...\n"
" %s -s setname -A enable | disable\n"
" %s -s setname -t [-f]\n"
" %s -s setname -r\n"
" %s [-s setname] -j [-M]\n"
" %s [-s setname] -w [-M]\n"
" %s -s setname -P [-M]\n"
" %s -s setname -b [-M]\n"
" %s -s setname -o [-M] [-h hostname]\n"
" %s [-s setname]\n"
"\n"
" drivename = cNtNdN no slice\n"
" [-M] for multi-owner set is optional except"
" on set creation\n"),
}
/*
* The svm.sync rc script relies heavily on the metaset output.
* Any changes to the metaset output MUST verify that the rc script
* does not break. Not doing so may potentially leave the system
* unusable. You have been WARNED.
*/
static int
{
int i, j;
int max_meds;
return (-1);
/*
* Only get set owner information for traditional diskset.
* This set owner information is stored in the node records
* for a MN diskset.
*/
if (!(MD_MNSET_DESC(sd))) {
return (-1);
}
return (-1);
if (MD_MNSET_DESC(sd)) {
"\nMulti-owner Set name = %s, Set number = %d, Master = %s\n"),
"Master and owner information unavailable "
"until joined (metaset -j)\n"));
}
} else {
"\nSet name = %s, Set number = %d\n"),
}
if (MD_MNSET_DESC(sd)) {
while (nd) {
/*
* Don't print nodes that aren't ok since they may be
* removed from config during a reconfig cycle. If a
* node was being added to a diskset and the entire
* cluster went down but the node being added was unable
* to reboot, there's no way to know if that node had
* its own node record set to OK or not. So, node
* record is left in ADD state during reconfig cycle.
* When that node reboots and returns to the cluster,
* the reconfig cycle will either remove the node
* record (if not marked OK on that node) or will mark
* it OK on all nodes.
* It is very important to only remove a node record
* from the other nodes when that node record is not
* marked OK on its own node - otherwise, different
* nodes would have different nodelists possibly
* causing different nodes to to choose different
* masters.
*
* Standard hostname field is 17 bytes but metaset
* will display up to MD_MAX_NODENAME, defined in
*/
continue;
}
(void) printf(
gettext(" %-17.*s %-12.12s %-4.4s\n"),
gettext("Yes"));
/* Should never be able to happen */
(void) printf(
gettext(" %-17.*s %-12.12s %-4.4s\n"),
gettext("No"));
(void) printf(
gettext(" %-17.*s %-12.12s %-4.4s\n"),
gettext("Yes"));
(void) printf(
gettext(" %-17.*s %-12.12s %-4.4s\n"),
gettext("No"));
}
}
} else {
(void) printf("\n%-19.19s %-5.5s\n",
for (i = 0; i < MD_MAXSIDES; i++) {
/* Skip empty slots */
continue;
/*
* Standard hostname field is 17 bytes but metaset will
* display up to MD_MAX_NODENAME, def in meta_basic.h
*/
gettext("No (auto)"))
}
}
(void) printf("\n%-19.19s %-7.7s\n",
return (-1);
for (i = 0; i < max_meds; i++) {
continue;
/*
* Standard hostname field is 17 bytes but metaset will
* display up to MD_MAX_NODENAME, def in meta_basic.h
*/
}
(void) printf("\n");
}
if (dd) {
int len = 0;
/*
* Building a format string on the fly that will
* be used in (f)printf. This allows the length
* of the ctd to vary from small to large without
* looking horrible.
*/
len += 2;
gettext("Drive"),
gettext("Dbase"));
gettext("No")));
}
}
return (0);
}
static int
{
int i;
/*
* print setname given.
*/
if (! metaislocalset(sp)) {
return (-1);
return (0);
}
return (-1);
/*
* Print all known sets
*/
for (i = 1; i < max_sets; i++) {
break;
mdclrerror(ep);
continue;
}
break;
}
return (-1);
return (0);
}
/*
* Print the current versionn of the cluster contract private interface.
*/
static void
{
}
/*
* Print the disks that make up the given disk set. This is used
* exclusively by Sun Cluster and is contract private.
* Should never be called with sname of a Multinode diskset.
*/
static int
{
/*
* During a deletion of a set the associated service is
* put offline. The SC3.0 reservation code calls disksuite
* to find a list of disks associated with the set so that
* it can release the reservation on those disks. In this
* case there won't be any disks or even a set left. So just
* return.
*/
return (0);
}
return (-1);
return (-1);
return (0);
}
static void
{
int c;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 's':
break;
default:
}
}
if (argc != 0)
}
}
}
}
static void
{
int c, created_set;
int multi_node = 0;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
multi_node = 1;
break;
case 'A':
/* verified sub-option in main */
break;
case 'a':
break;
case 'h':
case 'm':
"only one -m or -h option allowed"));
"conflicting options"));
if (c == 'h')
else
break;
case 'l':
"conflicting options"));
"%s: bad format\n"), optarg);
}
break;
case 'L':
/* Same criteria as -l */
"conflicting options"));
force_label = TRUE;
break;
case 's':
break;
default:
"unknown options"));
}
}
/* Can only use -A enable when creating the single-node set */
/*
* Add hosts
*/
}
}
/*
* Keep track of Cluster set creation. Need to complete
* the transaction no matter if the set was created or not.
*/
created_set = 0;
/*
* Have no set, cannot take the lock, so only take the
* local lock.
*/
sdssc_rval = 0;
if (multi_node) {
/*
* When running on a cluster system that
* does not support MN disksets, the routine
* sdssc_mo_create_begin will be bound
* to the SVM routine not_bound_error
* which returns SDSSC_NOT_BOUND_ERROR.
*
* When running on a cluster system that
* does support MN disksets, the routine
* sdssc_mo_create_begin will be bound to
* the sdssc_mo_create_begin routine in
* library libsdssc_so. A call to
* sdssc_mo_create_begin will return with
* either SDSSC_ERROR or SDSSC_OKAY. If
* an SDSSC_OKAY is returned, then the
* cluster framework has allocated a
* set number for this new set that is unique
* across traditional and MN disksets.
* Libmeta will get this unique set number
* by calling sdssc_get_index.
*
* When running on a non-cluster system,
* the routine sdssc_mo_create_begin
* will be bound to the SVM routine
* not_bound which returns SDSSC_NOT_BOUND.
* In this case, all sdssc routines will
* return SDSSC_NOT_BOUND. No need to check
* for return value of SDSSC_NOT_BOUND since
* the libmeta call to get the set number
* (sdssc_get_index) will also fail with
* SDSSC_NOT_BOUND causing libmeta to
* determine its own set number.
*/
if (sdssc_rval == SDSSC_NOT_BOUND_ERROR) {
"Cluster node does not support "
"multi-owner diskset operations");
} else if (sdssc_rval == SDSSC_ERROR) {
}
} else {
if (sdssc_rval == SDSSC_ERROR) {
}
}
/*
* Created diskset (as opposed to adding a
* host to an existing diskset).
*/
created_set = 1;
mdclrerror(ep);
} else {
}
if (MD_MNSET_DESC(sd)) {
multi_node = 1;
}
/*
* can't add hosts to an existing set & enable
* auto-take
*/
if (auto_take)
/*
* Have a valid set, take the set lock also.
*
* A MN diskset does not use the set meta_lock but
* instead uses the clnt_lock of rpc.metad and the
* use set meta_lock since class 1 messages are
* grabbing this lock and if this thread is holding
* the set meta_lock then no rpc.mdcommd suspend
* can occur.
*/
if (!multi_node) {
}
}
}
ep)) {
if (created_set)
if (!multi_node)
}
if (created_set)
else {
/*
* If adding hosts to existing diskset,
* call DCS svcs
*/
}
if (!multi_node)
}
/*
* Add mediators
*/
}
}
}
if (MD_MNSET_DESC(sd)) {
multi_node = 1;
}
}
/*
* A MN diskset does not use the set meta_lock but
* instead uses the clnt_lock of rpc.metad and the
* use set meta_lock since class 1 messages are
* grabbing this lock and if this thread is holding
* the set meta_lock then no rpc.mdcommd suspend
* can occur.
*/
if (!multi_node) {
}
}
if (!multi_node)
}
if (!multi_node)
}
/*
* Add drives
*/
}
}
/* Determine if diskset is a MN diskset or not */
}
if (MD_MNSET_DESC(sd)) {
multi_node = 1;
}
}
/* Make sure database size is within limits */
if (default_size == FALSE) {
"size (-l) is too small"));
"size (-l) is too big"));
}
/*
* Have a valid set, take the set lock also.
*
* A MN diskset does not use the set meta_lock but
* instead uses the clnt_lock of rpc.metad and the
* use set meta_lock since class 1 messages are
* grabbing this lock and if this thread is holding
* the set meta_lock then no rpc.mdcommd suspend
* can occur.
*/
if (!multi_node) {
}
}
/*
* If using the default size,
* then let's adjust the default to the minimum
* size currently in use.
*/
if (default_size) {
mdclrerror(ep);
else
}
if (!multi_node)
}
if (c == 0) {
"No drives specified to add.\n"));
if (!multi_node)
}
if (!multi_node)
}
/*
* MN disksets don't have a device id in the master block
* For traditional disksets, check for the drive device
* id not fitting in the master block
*/
if (!multi_node) {
int fd;
continue;
continue;
} else {
}
}
}
/*
* MN disksets don't use DCS clustering services.
* For traditional disksets:
* There's not really much we can do here if this call fails.
* The drives have been added to the set and DiskSuite believes
* it owns the drives.
* Relase the set and hope for the best.
*/
if ((!multi_node) &&
"Sun Clustering failed to make set primary\n"));
}
if (!multi_node)
}
static void
{
int c;
int multi_node = 0;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'b':
break;
case 's':
break;
default:
}
}
if (argc != 0)
}
}
if (MD_MNSET_DESC(sd)) {
multi_node = 1;
}
/*
* Have a valid set, take the set lock also.
*
* A MN diskset does not use the set meta_lock but
* instead uses the clnt_lock of rpc.metad and the
* use set meta_lock since class 1 messages are
* grabbing this lock and if this thread is holding
* the set meta_lock then no rpc.mdcommd suspend
* can occur.
*/
if (!multi_node) {
}
}
}
}
static void
{
int c;
int enable = 0;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'A':
/* verified sub-option in main */
enable = 1;
break;
case 's':
/* verified presence of setname in main */
break;
default:
}
}
}
}
}
}
}
static void
{
int c;
int multi_node = 0;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'd':
break;
case 'f':
break;
case 'h':
case 'm':
"only one -m or -h option allowed"));
if (c == 'h')
else
break;
case 's':
break;
default:
}
}
}
}
}
if (MD_MNSET_DESC(sd))
multi_node = 1;
}
/*
* Have a valid set, take the set lock also.
*
* A MN diskset does not use the set meta_lock but
* instead uses the clnt_lock of rpc.metad and the
* use set meta_lock since class 1 messages are
* grabbing this lock and if this thread is holding
* the set meta_lock then no rpc.mdcommd suspend
* can occur.
*/
if (!multi_node) {
}
}
/*
* Delete hosts
*/
/*
* If we don't own the set bail out here otherwise
* we could delete the node from the DCS service
* yet not delete the host from the set.
*/
if (!multi_node)
}
if (!metad_isautotakebyname(sname)) {
/*
* SC could have been installed after the set
* was created. We still want to be able to
* delete these sets.
*/
"Failed to delete hosts from DCS service"));
if (!multi_node)
}
}
"Failed to restore host(s) in DCS "
"database\n"));
}
if (!multi_node)
}
if (!multi_node)
}
/*
* Delete mediators
*/
if (!multi_node)
}
if (!multi_node)
}
/*
* Delete drives
*/
if (!multi_node)
}
if (c == 0) {
"No drives specified to delete.\n"));
if (!multi_node)
}
if (!multi_node)
}
if (!multi_node)
}
static void
{
int c;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'o':
break;
case 'h':
"only one -h option allowed"));
}
break;
case 's':
break;
default:
}
}
if (argc != 0)
}
}
} else {
}
}
}
static void
{
int c;
int bypass_cluster_purge = 0;
int ret = 0;
int multi_node = 0;
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'C':
bypass_cluster_purge = 1;
break;
case 'f':
break;
case 'P':
break;
case 's':
break;
default:
}
}
if (argc != 0)
}
}
}
}
if (MD_MNSET_DESC(sd))
multi_node = 1;
if (!multi_node) {
}
}
/* Must not own the set if purging it from this host */
/*
* Need to see if there are disks in the set, if not then
* there is no ownership but meta_check_ownership returns 0
*/
if (!multi_node)
}
("Must not be owner of the set when purging it\n"));
if (!multi_node)
}
}
/*
* Remove the node from the DCS service
*/
if (!bypass_cluster_purge) {
("Failed to purge hosts from DCS service"));
if (!multi_node)
}
}
ep)) != 0) {
if (!bypass_cluster_purge) {
SDSSC_ERROR) {
"Failed to restore host in DCS "
"database\n"));
}
}
if (!multi_node)
}
if (!multi_node)
}
static void
{
int c;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'q':
break;
case 's':
break;
default:
}
}
if (argc != 0)
}
}
}
(void) printf("The following tag(s) were found:\n");
}
}
/* Should never be called with sname of a Multinode diskset. */
static void
{
int c;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'C':
break;
case 's':
break;
case 'r':
break;
default:
}
}
if (argc > 0)
(cluster_release == SDSSC_False)) {
/*
* If the release is being done by the user via the CLI
* we need to notify the DCS to release this node as being
* the primary. The reason nothing else needs to be done
* is due to the fact that the reservation code will exec
* metaset -C release to complete the operation.
*/
if (rval == SDSSC_ERROR) {
"metaset: failed to notify DCS of release\n"));
}
}
/*
* It's entirely possible for the SC3.0 reservation code
* to call for DiskSet to release a diskset and have that
* diskset not exist. During a diskset removal DiskSuite
* maybe able to remove all traces of the diskset before
* the reservation code execs metaset -C release in which
* case the metasetname will fail, but the overall command
* shouldn't.
*/
else {
}
}
}
}
}
}
}
/* Should never be called with sname of a Multinode diskset. */
static void
{
int c;
int flags = 0;
int usetag = 0;
int set_take_rval;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'C':
break;
case 'f':
flags |= TAKE_FORCE;
break;
case 's':
break;
case 't':
break;
case 'u':
flags |= TAKE_USETAG;
break;
case 'y':
flags |= TAKE_USEIT;
break;
default:
}
}
if (argc > 1)
/*
* If we have a list of timeout value overrides, handle it here
*/
/*
* The use of the nullopts[] "token list" here is to make
* getsubopts() simply parse a comma separated list
* returning either "" or the contents of the field, the
* end condition is exaustion of the initial string, which
* is modified in the process.
*/
c = 0; /* re-use c as temp value of timeout */
if (c < 0) {
"time out values must be > 0"));
}
if (++pos > 3) {
"too many timeout values specified."));
}
if (c == 0) /* 0 or "" field uses default */
continue;
/*
* Assign temp value to appropriate structure member based on
* its position in the comma separated list.
*/
switch (pos) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
}
(cluster_take == SDSSC_False)) {
/*
* If the take is beging done by the user via the CLI we need
* to notify the DCS to make this current node the primary.
* The SC3.0 reservation code will in turn exec metaset with
* the -C take arg to complete this operation.
*/
SDSSC_ERROR) {
"metaset: failed to notify DCS of take\n"));
}
}
}
/*
* If we're running in a cluster environment and this
* node already owns the set. Don't bother trying to
* take the set again. There's one case where an adminstrator
* is adding disks to a set for the first time. metaset
* will take the ownership of the set at that point. During
* that add operation SC3.0 notices activity on the device
* and also tries to perform a take operation. The SC3.0 take
* will fail because the adminstrative add has the set locked
*/
}
}
/*
* If a 2 is returned from meta_set_take, this take was able to resolve
* an unresolved replicated disk (i.e. a disk is now available that
* had been missing during the import of the replicated diskset).
* Need to release the diskset and re-take in order to have
* the subdrivers re-snarf using the newly resolved (or newly mapped)
* devids. This also allows the namespace to be updated with the
* correct major names in the case where the disk being replicated
* was handled by a different driver than the replicated disk.
*/
if (set_take_rval == 2) {
"Need to release and take set to resolve names.");
}
}
if (set_take_rval == -1) {
}
}
/*
* Joins a node to a specific set or to all multinode disksets known
* by this node. If set is specified then caller should have verified
* that the set is a multinode diskset.
*
* If an error occurs, metaset exits with a 1.
* If there is no error, metaset exits with a 0.
*/
static void
{
int c;
char *p = buf;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'j':
break;
case 's':
break;
default:
}
}
if (argc > 1)
/*
* If no setname option was used, then join all disksets
* that this node knows about. Attempt to join all
* disksets that this node knows about.
*
* Additional text is added to the error messages during
* this section of code in order to help the user understand
* why the 'join of all sets' failed and which set caused
* the failure.
*/
/*
* Hold local set lock throughout this call to keep
* other actions from interfering (such as creating a new
* set, etc.).
*/
}
}
/*
* If no set name is given, then walk through all sets
* on this node which could include:
* - MN disksets
* - traditional disksets
* - non-existent disksets
* Attempt to join the MN disksets.
* If the join of one set fails, print out an error message
* about that set and continue the walk.
*/
}
/* Start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"Unable to get set %d information"),
setno);
mde_perror(ep, p);
cumm_err = 1;
mdclrerror(ep);
continue;
}
}
/* If setname is there, set desc should exist. */
"Unable to get set %s desc information"),
mde_perror(ep, p);
cumm_err = 1;
mdclrerror(ep);
continue;
}
/* Only check MN disksets */
if (!MD_MNSET_DESC(sd)) {
continue;
}
/*
* Return value of 0 is success.
* Return value of -1 means a failure.
* Return value of -2 means set could not be
* joined, but shouldn't cause an error.
* Reasons would be:
* - no drives in set
* - node already joined to set
* Return value of -3 means joined stale set.
* Can't check for all reasons here
* since set isn't locked yet across all
* nodes in the cluster. The call
* to libmeta routine, meta_set_join, will
* lock across the cluster and perform
* the checks.
*/
/* Print error of diskset join failure */
gettext("Join to diskset %s failed"),
mde_perror(ep, p);
cumm_err = 1;
mdclrerror(ep);
continue;
}
if (err == -3) {
/* Print error of diskset join failure */
gettext("Joined to stale diskset %s"),
mde_perror(ep, p);
mdclrerror(ep);
}
mdclrerror(ep);
}
}
/*
* Code for a specific set is much simpler.
* Error messages don't need extra text since specific setname
* was used.
* Don't need to lock the local set, just the specific set given.
*/
}
/*
* Fail command if meta_set_join returns -1.
*
* Return of 0 means that node joined set.
*
* Return of -2 means that node was unable to
* join a set since that set had no drives
* or that had already joined the set. No
* need to fail the command for these reasons.
*
* Return of -3 means that set is stale.
* Return a value of 66 to historically match traditional disksets.
*/
}
if (err == -3) {
/* Print error of diskset join failure */
gettext("Joined to stale diskset %s"),
}
}
/*
* Withdraws a node from a specific set or from all multinode disksets known
* by this node. If set is specified then caller should have verified
* that the set is a multinode diskset.
*
* If an error occurs, metaset exits with a 1.
* If there is no error, metaset exits with a 0.
*/
static void
{
int c;
char *p = buf;
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'M':
break;
case 'w':
break;
case 's':
break;
default:
}
}
if (argc > 1)
/*
* If no setname option was used, then withdraw from all disksets
* that this node knows about.
*
* Additional text is added to the error messages during
* this section of code in order to help the user understand
* why the 'withdraw from all sets' failed and which set caused
* the failure.
*/
/*
* Hold local set lock throughout this call to keep
* other actions from interfering (such as creating a new
* set, etc.).
*/
}
}
/*
* If no set name is given, then walk through all sets
* on this node which could include:
* - MN disksets
* - traditional disksets
* - non-existent disksets
* Attempt to withdraw from the MN disksets.
* If the withdraw of one set fails, print out an error
* message about that set and continue the walk.
*/
}
/* Start walking through all possible disksets */
/* No set for this setno - continue */
mdclrerror(ep);
continue;
} else {
"Unable to get set %d information"),
setno);
mde_perror(ep, p);
cumm_err = 1;
mdclrerror(ep);
continue;
}
}
/* If setname is there, set desc should exist. */
"Unable to get set %s desc information"),
mde_perror(ep, p);
cumm_err = 1;
mdclrerror(ep);
continue;
}
/* Only check MN disksets */
if (!MD_MNSET_DESC(sd)) {
continue;
}
/*
* Return value of 0 is success.
* Return value of -1 means a failure.
* Return value of -2 means set could not be
* withdrawn from, but this shouldn't cause
* an error. Reasons would be:
* - no drives in set
* - node already withdrawn from set
* Can't check for all reasons here
* since set isn't locked yet across all
* nodes in the cluster. The call
* to libmeta routine, meta_set_withdraw, will
* lock across the cluster and perform
* the checks.
*/
/* Print error of diskset withdraw failure */
gettext("Withdraw from diskset %s failed"),
mde_perror(ep, p);
mdclrerror(ep);
cumm_err = 1;
continue;
}
if (err == -2) {
mdclrerror(ep);
continue;
}
mdclrerror(ep);
}
}
/*
* Code for a specific set is much simpler.
* Error messages don't need extra text since specific setname
* was used.
* Don't need to lock the local set, just the specific set given.
*/
}
/*
* Fail command if meta_set_withdraw returns -1.
*
* Return of 0 means that node withdrew from set.
*
* Return of -2 means that node was unable to
* withdraw from a set since that set had no drives
* or node was not joined to set. No
* need to fail the command for these reasons.
*/
}
}
static void
{
/* reset and parse args */
optind = 1;
opterr = 1;
switch (c) {
case 'C':
if (cmd != ccnotspecified) {
}
cmd = clustertake;
cmd = clusterproxy;
cmd = clusterpurge;
} else {
}
break;
case 'h':
break;
case 's':
break;
case 'f':
case 't':
case 'u':
case 'y':
case 'r':
break;
default:
}
}
/* Now call the appropriate command function. */
switch (cmd) {
case clusterversion:
break;
case clusterdisksin:
}
break;
case clusterrelease:
if (multi_node) {
"-C release is not allowed on multi-owner"
" disksets"));
}
break;
case clustertake:
if (multi_node) {
"-C take is not allowed on multi-owner disksets"));
}
break;
case clusterproxy:
if (multi_node) {
"-C proxy is not allowed on multi-owner disksets"));
}
}
new_argc = 0;
for (x = 0; x < argc; x++) {
/*
* Need to skip the '-C proxy' args so
* just increase x by one and the work is
* done.
*/
x++;
} else {
new_argc++;
}
}
case SDSSC_ERROR:
break;
case SDSSC_NO_SERVICE:
if (hostname != SDSSC_PROXY_PRIMARY) {
}
break;
}
} else {
"Couldn't proxy command\n"));
}
break;
case clusterpurge:
break;
default:
break;
}
}
/*
* parse args and do it
*/
int
{
int mflag = 0;
int multi_node = 0;
/*
* Get the locale set up before calling any other routines
* with messages to ouput. Just in case we're not in a build
* environment, make sure that TEXT_DOMAIN gets set to
* something.
*/
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
if (sdssc_res == SDSSC_ERROR) {
"%s: Interface error with libsds_sc.so\n"), argv[0]);
exit(1);
}
/* initialize */
}
optind = 1;
opterr = 1;
/*
* NOTE: The "C" option is strictly for cluster use. it is not
* and should not be documented for the customer. - JST
*/
!= -1) {
switch (c) {
case 'M':
mflag = 1;
break;
case 'A':
"-A: enable or disable must be specified"));
break;
case 'a':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'b':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'd':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'C': /* cluster commands */
if (cmd != notspecified) {
}
break;
case 'f':
break;
case 'h':
break;
case 'j':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'l':
break;
case 'L':
break;
case 'm':
break;
case 'o':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'P':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'q':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'r':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 's':
break;
case 't':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'u':
break;
case 'w':
if (cmd != notspecified) {
"conflicting options"));
}
break;
case 'y':
break;
case '?':
if (optopt == '?')
/*FALLTHROUGH*/
default:
} else {
"unknown command"));
}
}
}
/* check if suncluster is installed and -A enable specified */
"cannot enable auto-take when SunCluster is installed\n"));
}
/*
* At this point we know that if the -A enable option is specified
* for an auto-take diskset that SC is not installed on the machine, so
* all of the sdssc calls will just be no-ops.
*/
/* list sets */
/*NOTREACHED*/
}
if (meta_check_root(ep) != 0) {
}
/* snarf MDDB */
if (meta_setup_db_locations(ep) != 0) {
}
/*
* If sname is a diskset - check for multi_node.
* It is possible for sname to not exist.
*/
/* Set exists - check for MN diskset */
}
if (MD_MNSET_DESC(sd)) {
/*
* If a MN diskset always set multi_node
* regardless of whether the -M option was
* used or not (mflag).
*/
multi_node = 1;
} else {
/*
* If a traditional diskset, mflag must
* not be set.
*/
if (mflag) {
"-M option only allowed "
"on multi-owner diskset"));
}
}
} else {
/*
* Set name does not exist, set multi_node
* based on -M option.
*/
if (mflag) {
multi_node = 1;
}
}
}
if (auto_take && multi_node) {
/* Can't mix multinode and auto-take on a diskset */
gettext("-A option not allowed on multi-owner diskset"));
}
/*
* MN disksets don't use DCS clustering services, so
* do not get primary_node for MN diskset since no command
* proxying is done to Primary cluster node. Do not proxy
* MN diskset commands of join and withdraw when issued without
* a valid setname.
* For traditional disksets: proxy all commands except a take
* and release. Use first host listed as the host to send the
* command to if there isn't already a primary
*/
switch (stat) {
case SDSSC_ERROR:
return (0);
case SDSSC_NO_SERVICE:
if (hostname != SDSSC_PROXY_PRIMARY) {
} else {
}
break;
}
/*
* We've got a complicated decision here regarding
* the hostname. If we didn't get a primary host
* and a host name wasn't supplied on the command line
* then we need to revert to SDSSC_PROXY_PRIMARY. Otherwise
* use what's been found.
*/
primary_node[0] == '\0' ?
&error) == SDSSC_PROXY_DONE) {
}
}
/* cluster-specific commands */
/*NOTREACHED*/
}
/* join MultiNode diskset */
/*
* If diskset specified, verify that it exists
* and is a multinode diskset.
*/
}
if (!multi_node) {
"-j option only allowed on "
"multi-owner diskset"));
}
}
/*
* Start mddoors daemon here.
* mddoors itself takes care there will be only one
* instance running, so starting it twice won't hurt
*/
/*NOTREACHED*/
}
/* withdraw from MultiNode diskset */
/*
* If diskset specified, verify that it exists
* and is a multinode diskset.
*/
}
if (!multi_node) {
"-w option only allowed on "
"multi-owner diskset"));
}
}
/*NOTREACHED*/
}
/* must have set for everything else */
/* add hosts or drives */
/*
* In the multi node case start mddoors daemon.
* mddoors itself takes care there will be
* only one instance running, so starting it twice won't hurt
*/
if (multi_node) {
}
/*NOTREACHED*/
}
/* re-balance the replicas */
/*NOTREACHED*/
}
/* delete hosts or drives */
/*NOTREACHED*/
}
/* check ownership */
/*NOTREACHED*/
}
/* purge the diskset */
/*NOTREACHED*/
}
/* query for data marks */
/*NOTREACHED*/
}
/* release ownership */
if (multi_node) {
/* Can't release multinode diskset */
"-r option not allowed on multi-owner diskset"));
} else {
/*NOTREACHED*/
}
}
/* take ownership */
if (multi_node) {
/* Can't take multinode diskset */
"-t option not allowed on multi-owner diskset"));
} else {
/*NOTREACHED*/
}
}
/* take ownership of auto-take sets */
if (auto_take) {
/*NOTREACHED*/
}
/*NOTREACHED*/
return (0);
}