5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Overview of poolcfg(1)
32 * poolcfg(1) implements a small grammar for manipulating pools configurations.
33 * yacc(1) is used to generate the parser and poolcfg.l contains a simple lexer
34 * (generted by lex(1)) to perform lexical processsing of the input.
36 * Refer to the poolcfg(1) manpage for more details of the grammar.
38 * The parser is designed so that all operations implement the same interface.
39 * This allows the parser to simply build up the command (using the cmd
40 * variable) by storing arguments and a pointer to the desired function in the
41 * cmd. The command is executed when the commands production is matched.
43 * Properties and associations are stored in simple linked lists and processed
44 * in the order submitted by the user.
51 #include <sys/types.h>
54 #include <sys/utsname.h>
65 "%s -c command [ -d | [ file ] ]\n" \
66 "%s -f command-file [-d | [ file ] ]\n\n"
70 " info [entity name]\n" \
71 " display configuration (or specified portion) in readable form\n" \
72 " create entity name [property-list]\n" \
73 " make an entity of the specified type and name\n" \
74 " destroy entity name\n" \
75 " remove the specified entity\n" \
76 " modify entity name [property-list]\n" \
77 " change the listed properties on the named entity\n" \
78 " associate pool name [resource-list]\n" \
79 " connect one or more resources to a pool, or replace one or more\n" \
80 " existing connections\n" \
81 " transfer to resource name [component-list]\n" \
82 " transfer one or more discreet components to a resource\n" \
83 " transfer [quantity] from resource src to tgt\n" \
84 " transfer a resource quantity from src to tgt\n" \
85 " transfer [quantity] to resource tgt from src\n" \
86 " transfer a resource quantity to tgt from src\n" \
88 " create a system entity, with one pool entity and resources to\n" \
89 " match current system configuration\n" \
90 " rename entity old_name to new_name\n" \
91 " change the name of the entity on the system to its new name\n\n" \
93 " ( proptype name = value [ ; proptype name = value ]* )\n" \
94 " where multiple definitions in the sentence for a given\n" \
95 " proptype, name pair are ignored; the last one provided is used.\n" \
96 " For property deletion, use \"~ proptype name\"\n\n" \
98 " ( resource name [; resource name ] )\n" \
99 " where multiple uses of a resource are ignored; the last provided\n" \
100 " is the one used.\n" \
101 " There is no deletion syntax for resource lists.\n" \
102 "component-list:\n" \
103 " ( cpu id [; cpu id ] )\n" \
104 " where multiple uses of the same component cause the last provided\n" \
105 " to be the one used.\n" \
106 " There is no deletion syntax for component lists.\n" \
108 " system | pool | pset | cpu\n" \
109 " where cpu is only valid for transfer, info and modify commands.\n" \
113 " boolean | int | uint | string | float\n\n"
115 int dofile
= PO_FALSE
; /* poolcfg.l uses this for errors */
116 int conf_edit_error
= POE_OK
; /* cached error for error reporting */
117 int conf_edit_errno
= 0; /* cached errno for error reporting */
118 int conf_list_error
= POE_OK
; /* cached error for error reporting */
119 int conf_list_errno
= 0; /* cached errno for error reporting */
120 static const char cmdname
[] = "poolcfg";
121 static const char cmd_options
[] = "c:df:h";
122 static void usage
(int);
123 static const char *max_suffix
= ".max";
124 static const char *min_suffix
= ".min";
126 static const char *conf_file
= NULL
; /* Location of target config */
127 static cmd_t
*cmd
= NULL
; /* Command being processed */
128 static pool_conf_t
*conf
= NULL
; /* Config to be processed */
129 static int edited
= PO_FALSE
; /* Has the configuration been changed */
134 extern
void yyerror(char *s
);
136 /* Utility functions */
137 static void arg_parse
(const char *);
138 static void file_parse
(const char *);
139 static cmd_t
*alloc_cmd
(void);
140 static prop_t
*alloc_prop
(prop_op_t
);
141 static assoc_t
*alloc_assoc
(int, const char *);
142 static void free_cmd
(cmd_t
*);
143 static void check_conf_name
(cmd_t
*);
144 static void prop_list_walk
(cmd_t
*, pool_elem_t
*);
145 static void assoc_list_walk
(cmd_t
*, pool_t
*);
146 static void transfer_list_walk
(cmd_t
*, pool_resource_t
*);
147 static void terminate
(void);
148 static pool_component_t
*get_cpu
(const char *);
149 static void process_min_max
(pool_resource_t
*);
152 static void parser_conf_info
(cmd_t
*);
153 static void parser_pool_info
(cmd_t
*);
154 static void parser_resource_info
(cmd_t
*, const char *);
155 static void parser_pset_info
(cmd_t
*);
156 static void parser_cpu_info
(cmd_t
*);
158 /* Create Commands */
159 static void parser_conf_create
(cmd_t
*);
160 static void parser_pool_create
(cmd_t
*);
161 static void parser_resource_create
(cmd_t
*, const char *);
162 static void parser_pset_create
(cmd_t
*);
164 /* Destroy Commands */
165 static void parser_conf_destroy
(cmd_t
*);
166 static void parser_pool_destroy
(cmd_t
*);
167 static void parser_resource_destroy
(cmd_t
*, const char *);
168 static void parser_pset_destroy
(cmd_t
*);
170 /* Modify Commands */
171 static void parser_conf_modify
(cmd_t
*);
172 static void parser_pool_modify
(cmd_t
*);
173 static void parser_resource_modify
(cmd_t
*, const char *);
174 static void parser_pset_modify
(cmd_t
*);
175 static void parser_cpu_modify
(cmd_t
*);
177 /* Associate Commands */
178 static void parser_pool_associate
(cmd_t
*);
180 /* Assign Commands */
181 static void parser_resource_xtransfer
(cmd_t
*);
182 static void parser_resource_transfer
(cmd_t
*);
184 /* Discover Commands */
185 static void parser_conf_discover
(cmd_t
*);
187 /* Rename Commands */
188 static void parser_rename
(cmd_t
*, pool_elem_t
*, const char *);
189 static void parser_conf_rename
(cmd_t
*);
190 static void parser_pool_rename
(cmd_t
*);
191 static void parser_pset_rename
(cmd_t
*);
210 %token PCC_INFO PCC_CREATE PCC_DESTROY PCC_MODIFY PCC_ASSOC PCC_DISC PCC_RENAME
212 %token PCK_FROM PCK_TO PCK_OPENLST PCK_CLOSELST PCK_SEPLST PCK_ASSIGN PCK_UNDEF
214 %token PCV_FILENAME PCV_SYMBOL PCV_VAL_INT PCV_VAL_UINT PCV_VAL_FLOAT
215 PCV_VAL_STRING PCV_VAL_BOOLEAN
216 %token PCT_INT PCT_UINT PCT_BOOLEAN PCT_FLOAT PCT_STRING
217 %token PCE_SYSTEM PCE_POOL PCE_PSET PCE_CPU
219 %type
<ival
> PCV_VAL_INT
220 %type
<uval
> PCV_VAL_UINT
221 %type
<bval
> PCV_VAL_BOOLEAN
222 %type
<dval
> PCV_VAL_FLOAT
223 %type
<sval
> PCV_VAL_STRING
224 %type
<sval
> PCV_SYMBOL
225 %type
<sval
> PCV_FILENAME
227 %type
<ival
> PCC_INFO
228 %type
<ival
> PCE_SYSTEM PCE_POOL PCE_PSET PCE_CPU
229 %type
<ival
> entity proptype info_entity modify_entity
230 %type
<sval
> name src tgt
232 %type
<cmd
> list_command info_command edit_command create_command
233 destroy_command modify_command associate_command discover_command
234 rename_command transfer_command transfer_qty transfer_components
235 %type
<prop
> prop_remove prop_assign prop_op prop_ops property_list
236 %type
<assoc
> resource_assign resource_assigns resource_list
237 %type
<assoc
> component_assign component_assigns component_list
239 %type
<ival
> resource component
255 | command
error { YYERROR;};
257 command: list_command
260 if
(conf_edit_error
!= POE_OK
) {
261 if
($1->cmd
!= parser_conf_create
&&
262 $1->cmd
!= parser_conf_discover
) {
263 die
(gettext
(ERR_CONF_LOAD
), conf_file
,
264 get_errstr_err
(conf_edit_error
,
271 list_command: info_command
273 if
(conf_list_error
!= POE_OK
) {
274 if
($1->cmd
!= parser_conf_create
&&
275 $1->cmd
!= parser_conf_discover
) {
276 die
(gettext
(ERR_CONF_LOAD
), conf_file
,
277 get_errstr_err
(conf_list_error
,
282 | discover_command
{conf_list_error
= conf_edit_error
= POE_OK
;};
284 edit_command: create_command
291 info_command: PCC_INFO
293 if
(($$
= alloc_cmd
()) == NULL
)
296 $$
->cmd
= &parser_conf_info
;
298 | PCC_INFO info_entity name
300 if
(($$
= alloc_cmd
()) == NULL
)
305 $$
->cmd
= &parser_conf_info
;
308 $$
->cmd
= &parser_pool_info
;
311 $$
->cmd
= &parser_pset_info
;
314 $$
->cmd
= &parser_cpu_info
;
317 warn
(gettext
(ERR_UNKNOWN_ENTITY
), $2);
323 create_command: PCC_CREATE entity name
325 if
(($$
= alloc_cmd
()) == NULL
)
330 $$
->cmd
= &parser_conf_create
;
332 * When creating a new system element, ensure
333 * pre-existing errors are ignored.
335 conf_list_error
= conf_edit_error
= POE_OK
;
338 $$
->cmd
= &parser_pool_create
;
341 $$
->cmd
= &parser_pset_create
;
344 warn
(gettext
(ERR_UNKNOWN_ENTITY
), $2);
349 | create_command property_list
;
351 destroy_command: PCC_DESTROY entity name
353 if
(($$
= alloc_cmd
()) == NULL
)
358 $$
->cmd
= &parser_conf_destroy
;
361 $$
->cmd
= &parser_pool_destroy
;
364 $$
->cmd
= &parser_pset_destroy
;
367 warn
(gettext
(ERR_UNKNOWN_ENTITY
), $2);
373 modify_command: PCC_MODIFY modify_entity name
375 if
(($$
= alloc_cmd
()) == NULL
)
380 $$
->cmd
= &parser_conf_modify
;
383 $$
->cmd
= &parser_pool_modify
;
386 $$
->cmd
= &parser_pset_modify
;
389 $$
->cmd
= &parser_cpu_modify
;
392 warn
(gettext
(ERR_UNKNOWN_ENTITY
), $2);
397 | modify_command property_list
;
399 associate_command: PCC_ASSOC PCE_POOL name
401 if
(($$
= alloc_cmd
()) == NULL
)
404 $$
->cmd
= &parser_pool_associate
;
407 | associate_command resource_list
;
409 transfer_command: transfer_qty
410 | transfer_components
;
412 transfer_components: PCC_TRANSFER PCK_TO PCE_PSET name
414 if
(($$
= alloc_cmd
()) == NULL
)
417 $$
->cmd
= &parser_resource_xtransfer
;
420 | transfer_components component_list
;
422 transfer_qty: PCC_TRANSFER PCV_VAL_UINT PCK_FROM PCE_PSET src PCK_TO tgt
424 if
(($$
= alloc_cmd
()) == NULL
)
427 $$
->cmd
= &parser_resource_transfer
;
432 | PCC_TRANSFER PCV_VAL_UINT PCK_TO PCE_PSET tgt PCK_FROM src
434 if
(($$
= alloc_cmd
()) == NULL
)
437 $$
->cmd
= &parser_resource_transfer
;
443 discover_command: PCC_DISC
445 if
(($$
= alloc_cmd
()) == NULL
)
448 $$
->cmd
= &parser_conf_discover
;
451 rename_command: PCC_RENAME entity name PCK_TO name
453 if
(($$
= alloc_cmd
()) == NULL
)
458 $$
->cmd
= &parser_conf_rename
;
461 $$
->cmd
= &parser_pool_rename
;
464 $$
->cmd
= &parser_pset_rename
;
467 warn
(gettext
(ERR_UNKNOWN_ENTITY
), $2);
474 modify_entity: entity
475 | PCE_CPU
{$$
= PCE_CPU
;};
478 | PCE_CPU
{$$
= PCE_CPU
;};
480 entity: PCE_SYSTEM
{$$
= PCE_SYSTEM
;}
481 | PCE_POOL
{$$
= PCE_POOL
;}
482 | PCE_PSET
{$$
= PCE_PSET
;};
490 value: PCV_VAL_INT
{ $$.i
= $1;}
491 | PCV_VAL_UINT
{ $$.u
= $1;}
492 | PCV_VAL_FLOAT
{ $$.d
= $1;}
493 | PCV_VAL_BOOLEAN
{ $$.b
= $1;}
494 | PCV_VAL_STRING
{ $$.s
= $1;};
496 prop_remove: PCK_UNDEF proptype name
498 if
(($$
= alloc_prop
(po_remove
)) == NULL
)
511 for
(prop
= cmd
->cmd_prop_list
; prop
!= NULL
;
512 prop
= prop
->prop_next
)
513 prev
= prop
; /* Find end of list */
515 prev
->prop_next
= $1;
517 cmd
->cmd_prop_list
= $1;
518 $$
= cmd
->cmd_prop_list
;
520 | prop_ops PCK_SEPLST prop_op
525 for
(prop
= cmd
->cmd_prop_list
; prop
!= NULL
;
526 prop
= prop
->prop_next
)
527 prev
= prop
; /* Find end of list */
529 prev
->prop_next
= $3;
531 cmd
->cmd_prop_list
= $3;
532 $$
= cmd
->cmd_prop_list
;
536 prop_assign: proptype name PCK_ASSIGN value
538 if
(($$
= alloc_prop
(po_create
)) == NULL
)
543 pool_value_set_int64
($$
->prop_value
, $4.i
);
546 pool_value_set_uint64
($$
->prop_value
, $4.u
);
549 pool_value_set_bool
($$
->prop_value
, $4.b
);
552 pool_value_set_double
($$
->prop_value
, $4.d
);
555 pool_value_set_string
($$
->prop_value
, $4.s
);
560 property_list: PCK_OPENLST prop_ops PCK_CLOSELST
565 resource_assigns: resource_assign
567 assoc_t
*assoc
= NULL
;
568 assoc_t
*prev
= NULL
;
570 for
(assoc
= cmd
->cmd_assoc_list
; assoc
!= NULL
;
571 assoc
= assoc
->assoc_next
)
572 prev
= assoc
; /* Find end of list */
574 prev
->assoc_next
= $1;
576 cmd
->cmd_assoc_list
= $1;
577 $$
= cmd
->cmd_assoc_list
;
580 | resource_assigns PCK_SEPLST resource_assign
582 assoc_t
*assoc
= NULL
;
583 assoc_t
*prev
= NULL
;
585 for
(assoc
= cmd
->cmd_assoc_list
; assoc
!= NULL
;
586 assoc
= assoc
->assoc_next
)
587 prev
= assoc
; /* Find end of list */
589 prev
->assoc_next
= $3;
593 resource_assign: resource name
595 if
(($$
= alloc_assoc
($1, $2)) == NULL
)
599 resource: PCE_PSET
{$$
= PCE_PSET
;};
601 resource_list: PCK_OPENLST resource_assigns PCK_CLOSELST
606 component_assigns: component_assign
608 assoc_t
*assoc
= NULL
;
609 assoc_t
*prev
= NULL
;
611 for
(assoc
= cmd
->cmd_assoc_list
; assoc
!= NULL
;
612 assoc
= assoc
->assoc_next
)
613 prev
= assoc
; /* Find end of list */
615 prev
->assoc_next
= $1;
617 cmd
->cmd_assoc_list
= $1;
618 $$
= cmd
->cmd_assoc_list
;
621 | component_assigns PCK_SEPLST component_assign
623 assoc_t
*assoc
= NULL
;
624 assoc_t
*prev
= NULL
;
626 for
(assoc
= cmd
->cmd_assoc_list
; assoc
!= NULL
;
627 assoc
= assoc
->assoc_next
)
628 prev
= assoc
; /* Find end of list */
630 prev
->assoc_next
= $3;
634 component_list: PCK_OPENLST component_assigns PCK_CLOSELST
639 component_assign: component name
641 if
(($$
= alloc_assoc
($1, $2)) == NULL
)
645 component: PCE_CPU
{$$
= PCE_CPU
;};
647 proptype: PCT_INT
{$$
= PCT_INT
;}
648 | PCT_UINT
{$$
= PCT_UINT
;}
649 | PCT_BOOLEAN
{$$
= PCT_BOOLEAN
;}
650 | PCT_FLOAT
{$$
= PCT_FLOAT
;}
651 | PCT_STRING
{$$
= PCT_STRING
;};
656 #define TEXT_DOMAIN "SYS_TEST"
660 main
(int argc
, char *argv
[])
663 int docmd
= PO_FALSE
;
665 (void) getpname
(argv
[0]);
666 (void) setlocale
(LC_ALL
, "");
667 (void) textdomain
(TEXT_DOMAIN
);
668 if
(atexit
(terminate
) != 0) {
669 die
(gettext
(ERR_SET_TERM
), get_errstr
());
672 conf_file
= pool_static_location
();
675 while
((opt
= getopt
(argc
, argv
, cmd_options
)) != (int)EOF
) {
678 case
'c': /* Process command line */
679 if
(dofile
== PO_TRUE
)
684 case
'd': /* Manipulate dynamic configuration */
685 conf_file
= pool_dynamic_location
();
687 case
'f': /* Process command file */
688 if
(docmd
== PO_TRUE
)
702 if
(docmd
== PO_FALSE
&& dofile
== PO_FALSE
)
705 if
(optind
== argc
- 1) {
706 if
(strcmp
(conf_file
, pool_dynamic_location
()) == 0)
708 conf_file
= argv
[optind
];
709 } else if
(optind
< argc
- 1)
712 if
((conf
= pool_conf_alloc
()) == NULL
) {
713 die
(gettext
(ERR_ALLOC_ELEMENT
), gettext
(CONFIGURATION
),
717 * Opening a conf is complex, since we may be opening one of the
719 * - An existing configuration that we can modify
720 * - An existing configuration that we can't modify
721 * - A new configuration that we can modify
722 * - A new configuration that we can't modify
723 * The parser_conf_discover() function closes the file and reopens
724 * in PO_CREAT mode, so we only need be concerned here with the
726 * Always try to open RDWR, if fail try RDONLY. Don't check
727 * if that fails, since we may be trying to discover a configuration
728 * in which case it's valid for both open attempts to fail. Later, when
729 * processing commands, if we don't have a valid configuration and
730 * we are trying to process a command which isn't a create or a discover
731 * we will fail the command as there is no valid configuration to
734 if
(pool_conf_open
(conf
, conf_file
, PO_RDWR
) != 0) {
735 conf_edit_error
= pool_error
();
736 conf_edit_errno
= errno
;
737 if
(pool_conf_open
(conf
, conf_file
, PO_RDONLY
) != 0) {
738 conf_list_error
= pool_error
();
739 conf_list_errno
= errno
;
743 if
(yyparse() == 0) {
744 if
(pool_conf_status
(conf
) >= POF_VALID
) {
745 if
(pool_conf_validate
(conf
, POV_STRICT
) == PO_FAIL
) {
746 die
(gettext
(ERR_VALIDATION_FAILED
),
750 * If the user attempted to change the configuration,
751 * then we should try to save the changes.
753 if
(edited
== PO_TRUE
) {
754 if
(pool_conf_commit
(conf
, 0) == PO_FAIL
) {
755 die
(gettext
(ERR_CONFIG_SAVE_FAILED
),
759 pool_conf_close
(conf
);
762 die
(gettext
(ERR_CMDPARSE_FAILED
));
766 * Cleanup is performed in terminate(), using atexit
773 * Invoke the appropriate libpool info function and display the returned
777 parser_conf_info
(cmd_t
*cmd
)
780 const char *tgt
= cmd
->cmd_tgt1
;
781 pool_value_t
*pv
= NULL
;
784 if
((pe
= pool_conf_to_elem
(conf
)) == NULL
)
785 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
786 gettext
(CONFIGURATION
), "unknown", get_errstr
());
789 check_conf_name
(cmd
);
791 if
((pv
= pool_value_alloc
()) == NULL
)
792 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
793 gettext
(CONFIGURATION
), "unknown", get_errstr
());
794 if
(pool_get_property
(conf
, pe
, "system.name", pv
) ==
796 pool_value_get_string
(pv
, &tgt
) != PO_SUCCESS
)
797 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
798 gettext
(CONFIGURATION
), "unknown", get_errstr
());
800 if
((info_buf
= pool_conf_info
(conf
, PO_TRUE
)) == NULL
) {
801 die
(gettext
(ERR_GET_ELEMENT_DETAILS
), gettext
(CONFIGURATION
),
807 (void) printf
("%s\n", info_buf
);
812 parser_pool_info
(cmd_t
*cmd
)
817 if
((pool
= pool_get_pool
(conf
, cmd
->cmd_tgt1
)) == NULL
)
818 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
821 if
((info_buf
= pool_info
(conf
, pool
, PO_TRUE
)) == NULL
)
822 die
(gettext
(ERR_GET_ELEMENT_DETAILS
), gettext
(POOL
),
823 cmd
->cmd_tgt1
, get_errstr
());
824 (void) printf
("%s\n", info_buf
);
829 parser_resource_info
(cmd_t
*cmd
, const char *type
)
831 pool_resource_t
*resource
;
834 if
((resource
= pool_get_resource
(conf
, type
, cmd
->cmd_tgt1
)) == NULL
)
835 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(RESOURCE
),
836 cmd
->cmd_tgt1
, get_errstr
());
838 if
((info_buf
= pool_resource_info
(conf
, resource
, PO_TRUE
)) == NULL
)
839 die
(gettext
(ERR_GET_ELEMENT_DETAILS
), gettext
(RESOURCE
),
840 cmd
->cmd_tgt1
, get_errstr
());
841 (void) printf
("%s\n", info_buf
);
846 parser_pset_info
(cmd_t
*cmd
)
848 parser_resource_info
(cmd
, PSET
);
852 parser_cpu_info
(cmd_t
*cmd
)
854 pool_component_t
*comp
;
857 if
((comp
= get_cpu
(cmd
->cmd_tgt1
)) == NULL
)
858 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(CPU
),
859 cmd
->cmd_tgt1
, get_errstr
());
860 if
((info_buf
= pool_component_info
(conf
, comp
, PO_TRUE
)) == NULL
) {
861 die
(gettext
(ERR_GET_ELEMENT_DETAILS
), gettext
(CPU
),
862 cmd
->cmd_tgt1
, get_errstr
());
864 (void) printf
("%s\n", info_buf
);
870 * Invoke the appropriate libpool create function and perform any requested
871 * property operations.
874 parser_conf_create
(cmd_t
*cmd
)
876 const char *tmp_name
;
879 if
(conf
!= NULL
&& pool_conf_status
(conf
) >= POF_VALID
)
880 pool_conf_close
(conf
);
881 if
(pool_conf_open
(conf
, conf_file
, PO_CREAT
) != 0) {
882 die
(gettext
(ERR_CREATE_ELEMENT
), gettext
(CONFIGURATION
),
883 cmd
->cmd_tgt1
, get_errstr
());
885 tmp_name
= cmd
->cmd_tgt1
;
886 cmd
->cmd_tgt1
= cmd
->cmd_tgt2
;
887 cmd
->cmd_tgt2
= tmp_name
;
888 parser_conf_rename
(cmd
);
889 if
((pe
= pool_conf_to_elem
(conf
)) == NULL
)
890 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
891 gettext
(CONFIGURATION
), "unknown", get_errstr
());
892 prop_list_walk
(cmd
, pe
);
896 parser_pool_create
(cmd_t
*cmd
)
900 if
((pool
= pool_create
(conf
, cmd
->cmd_tgt1
)) == NULL
)
901 die
(gettext
(ERR_CREATE_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
903 prop_list_walk
(cmd
, pool_to_elem
(conf
, pool
));
907 parser_resource_create
(cmd_t
*cmd
, const char *type
)
909 pool_resource_t
*resource
;
911 if
((resource
= pool_resource_create
(conf
, type
, cmd
->cmd_tgt1
))
913 die
(gettext
(ERR_CREATE_ELEMENT
), type
, cmd
->cmd_tgt1
,
916 process_min_max
(resource
);
918 prop_list_walk
(cmd
, pool_resource_to_elem
(conf
, resource
));
922 parser_pset_create
(cmd_t
*cmd
)
924 parser_resource_create
(cmd
, PSET
);
929 * Rename the target by calling pool_put_property for the name property.
932 parser_rename
(cmd_t
*cmd
, pool_elem_t
*pe
, const char *name
)
936 if
((pv
= pool_value_alloc
()) == NULL
) {
937 die
(gettext
(ERR_ALLOC_ELEMENT
), gettext
(RESOURCE
),
940 pool_value_set_string
(pv
, cmd
->cmd_tgt2
);
941 if
(pool_put_property
(conf
, pe
, name
, pv
) != 0)
942 die
(gettext
(ERR_PUT_PROPERTY
), name
, get_errstr
());
947 parser_conf_rename
(cmd_t
*cmd
)
951 if
((pe
= pool_conf_to_elem
(conf
)) == NULL
)
952 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
953 gettext
(CONFIGURATION
), "unknown", get_errstr
());
955 if
(cmd
->cmd_tgt1
!= NULL
)
956 check_conf_name
(cmd
);
958 parser_rename
(cmd
, pe
, SYSTEM_NAME
);
962 parser_pool_rename
(cmd_t
*cmd
)
966 if
((pool
= pool_get_pool
(conf
, cmd
->cmd_tgt1
)) == NULL
)
967 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
970 parser_rename
(cmd
, pool_to_elem
(conf
, pool
), POOL_NAME
);
974 parser_pset_rename
(cmd_t
*cmd
)
976 pool_resource_t
*resource
;
978 if
((resource
= pool_get_resource
(conf
, PSET
, cmd
->cmd_tgt1
)) == NULL
)
979 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(PSET
), cmd
->cmd_tgt1
,
982 parser_rename
(cmd
, pool_resource_to_elem
(conf
, resource
), PSET_NAME
);
987 * Invoke the appropriate libpool destroy function to remove the target of the
988 * command from the configuration.
991 parser_conf_destroy
(cmd_t
*cmd
)
993 if
(cmd
->cmd_tgt1
!= NULL
)
994 check_conf_name
(cmd
);
996 if
(pool_conf_remove
(conf
) != 0)
997 die
(gettext
(ERR_DESTROY_ELEMENT
), gettext
(CONFIGURATION
),
998 cmd
->cmd_tgt1
, get_errstr
());
1002 parser_pool_destroy
(cmd_t
*cmd
)
1006 if
((pool
= pool_get_pool
(conf
, cmd
->cmd_tgt1
)) == NULL
)
1007 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
1010 if
(pool_destroy
(conf
, pool
) != 0)
1011 die
(gettext
(ERR_DESTROY_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
1016 parser_resource_destroy
(cmd_t
*cmd
, const char *type
)
1018 pool_resource_t
*resource
;
1020 if
((resource
= pool_get_resource
(conf
, type
, cmd
->cmd_tgt1
)) == NULL
)
1021 die
(gettext
(ERR_LOCATE_ELEMENT
), type
, cmd
->cmd_tgt1
,
1024 if
(pool_resource_destroy
(conf
, resource
) != 0)
1025 die
(gettext
(ERR_DESTROY_ELEMENT
), type
, cmd
->cmd_tgt1
,
1030 parser_pset_destroy
(cmd_t
*cmd
)
1032 parser_resource_destroy
(cmd
, PSET
);
1037 * Perform any requested property operations.
1040 parser_conf_modify
(cmd_t
*cmd
)
1044 if
((pe
= pool_conf_to_elem
(conf
)) == NULL
)
1045 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
1046 gettext
(CONFIGURATION
), "unknown", get_errstr
());
1048 if
(cmd
->cmd_tgt1
!= NULL
)
1049 check_conf_name
(cmd
);
1051 prop_list_walk
(cmd
, pe
);
1055 parser_pool_modify
(cmd_t
*cmd
)
1059 if
((pool
= pool_get_pool
(conf
, cmd
->cmd_tgt1
)) == NULL
)
1060 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
1062 prop_list_walk
(cmd
, pool_to_elem
(conf
, pool
));
1066 parser_resource_modify
(cmd_t
*cmd
, const char *type
)
1068 pool_resource_t
*resource
;
1070 if
((resource
= pool_get_resource
(conf
, type
, cmd
->cmd_tgt1
)) == NULL
)
1071 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(RESOURCE
),
1072 cmd
->cmd_tgt1
, get_errstr
());
1074 process_min_max
(resource
);
1076 prop_list_walk
(cmd
, pool_resource_to_elem
(conf
, resource
));
1080 parser_pset_modify
(cmd_t
*cmd
)
1082 parser_resource_modify
(cmd
, PSET
);
1086 parser_cpu_modify
(cmd_t
*cmd
)
1088 pool_component_t
*comp
;
1090 if
((comp
= get_cpu
(cmd
->cmd_tgt1
)) == NULL
)
1091 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(CPU
),
1092 cmd
->cmd_tgt1
, get_errstr
());
1093 prop_list_walk
(cmd
, pool_component_to_elem
(conf
, comp
));
1098 * Invoke the libpool pool_conf_open function so that discovery will be
1104 parser_conf_discover
(cmd_t
*cmd
)
1106 struct utsname utsname
;
1108 if
(strcmp
(conf_file
, pool_dynamic_location
()) == 0)
1111 if
(uname
(&utsname
) < 0)
1112 die
(gettext
(ERR_CREATE_ELEMENT
), gettext
(CONFIGURATION
),
1113 "unknown", get_errstr
());
1115 if
(conf
!= NULL
&& pool_conf_status
(conf
) >= POF_VALID
)
1116 pool_conf_close
(conf
);
1117 if
(pool_conf_open
(conf
, pool_dynamic_location
(), PO_RDONLY
) != 0) {
1118 die
(gettext
(ERR_CREATE_ELEMENT
), gettext
(CONFIGURATION
),
1119 utsname.nodename
, get_errstr
());
1121 if
(pool_conf_export
(conf
, conf_file
, POX_NATIVE
) != 0) {
1122 die
(gettext
(ERR_CREATE_ELEMENT
), gettext
(CONFIGURATION
),
1123 utsname.nodename
, get_errstr
());
1125 (void) pool_conf_close
(conf
);
1126 if
(pool_conf_open
(conf
, conf_file
, PO_RDWR
) != 0) {
1127 die
(gettext
(ERR_CREATE_ELEMENT
), gettext
(CONFIGURATION
),
1128 utsname.nodename
, get_errstr
());
1133 * Associate Commands
1134 * Walk the list of specified associations so that the target pool will be
1135 * associated with the required resources.
1139 parser_pool_associate
(cmd_t
*cmd
)
1143 if
((pool
= pool_get_pool
(conf
, cmd
->cmd_tgt1
)) == NULL
)
1144 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(POOL
), cmd
->cmd_tgt1
,
1146 assoc_list_walk
(cmd
, pool
);
1151 * Walk the list of specified assignations so that the required
1152 * components will be assigned to the target resource.
1156 parser_resource_xtransfer
(cmd_t
*cmd
)
1158 pool_resource_t
*resource
;
1160 if
((resource
= pool_get_resource
(conf
, PSET
, cmd
->cmd_tgt1
)) == NULL
)
1161 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(RESOURCE
),
1162 cmd
->cmd_tgt1
, get_errstr
());
1163 transfer_list_walk
(cmd
, resource
);
1168 * Transfer the specified quantity of resource between the src and the tgt.
1172 parser_resource_transfer
(cmd_t
*cmd
)
1174 pool_resource_t
*src
;
1175 pool_resource_t
*tgt
;
1177 if
((src
= pool_get_resource
(conf
, PSET
, cmd
->cmd_tgt1
)) == NULL
)
1178 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(RESOURCE
),
1179 cmd
->cmd_tgt1
, get_errstr
());
1180 if
((tgt
= pool_get_resource
(conf
, PSET
, cmd
->cmd_tgt2
)) == NULL
)
1181 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(RESOURCE
),
1182 cmd
->cmd_tgt2
, get_errstr
());
1183 if
(pool_resource_transfer
(conf
, src
, tgt
, cmd
->cmd_qty
) != PO_SUCCESS
)
1184 die
(gettext
(ERR_XFER_QUANTITY
), cmd
->cmd_qty
,
1185 cmd
->cmd_tgt1
, cmd
->cmd_tgt2
, get_errstr
());
1189 * arg_parse() puts the parser into command parsing mode. Create a tmpfile
1190 * and instruct the parser to read instructions from this location by setting
1191 * yyin to the value returned by tmpfile. Write the command into the file.
1192 * Then seek back to to the start of the file so that the parser can read
1196 arg_parse
(const char *command
)
1198 if
((yyin
= tmpfile
()) == NULL
)
1199 die
(gettext
(ERR_CMD_FILE_INIT
), strerror
(errno
));
1200 if
(fwrite
(command
, strlen
(command
), 1, yyin
) != 1)
1201 die
(gettext
(ERR_CMD_FILE_INIT
), strerror
(errno
));
1202 if
(fseek
(yyin
, 0, SEEK_SET
) != 0)
1203 die
(gettext
(ERR_CMD_FILE_INIT
), strerror
(errno
));
1207 * file_parse() puts the parser into command file parsing mode. Firstly check
1208 * to see if the user wishes to parse from standard input, if so do nothing.
1209 * Attempt to open the specified file and instruct the parser to read
1210 * instructions from this location by setting yyin to the value returned by
1214 file_parse
(const char *file
)
1216 if
(strcmp
(file
, "-") == 0)
1219 if
((yyin
= fopen
(file
, "r")) == NULL
) {
1220 die
(gettext
(ERR_CMD_FILE_INIT
), strerror
(errno
));
1225 * free_cmd() releases the resources associated with the supplied cmd parameter.
1228 free_cmd
(cmd_t
*cmd
)
1230 prop_t
*prop
= cmd
->cmd_prop_list
;
1231 assoc_t
*assoc
= cmd
->cmd_assoc_list
;
1233 free
((void *)cmd
->cmd_tgt1
);
1234 free
((void *)cmd
->cmd_tgt2
);
1235 while
(prop
!= NULL
) {
1237 prop
= prop
->prop_next
;
1238 pool_value_free
(tmp
->prop_value
);
1239 free
((void *)tmp
->prop_name
);
1242 while
(assoc
!= NULL
) {
1243 assoc_t
*tmp
= assoc
;
1244 assoc
= assoc
->assoc_next
;
1245 free
((void *)tmp
->assoc_name
);
1252 * alloc_cmd() allocates the required resources for a cmd_t. On failure, a
1253 * warning is issued and NULL is returned.
1260 if
((cmd
= malloc
(sizeof
(cmd_t
))) == NULL
) {
1261 warn
(gettext
(ERR_CMD_LINE_ALLOC
));
1265 (void) memset
(cmd
, 0, sizeof
(cmd_t
));
1271 * alloc_prop() allocates the required resources for a prop_t. On failure, a
1272 * warning is issued and NULL is returned. The prop_t is initialised with
1273 * the prop_op_t parameter.
1276 alloc_prop
(prop_op_t op
)
1280 if
((prop
= malloc
(sizeof
(prop_t
))) == NULL
) {
1281 warn
(gettext
(ERR_PROP_ALLOC
));
1285 (void) memset
(prop
, 0, sizeof
(prop_t
));
1286 if
((prop
->prop_value
= pool_value_alloc
()) == NULL
) {
1287 warn
(gettext
(ERR_PROP_ALLOC
));
1296 * alloc_assoc() allocates the required resources for an assoc_t. On failure, a
1297 * warning is issued and NULL is returned. The assoc_t is initialised with
1298 * the type and name of the association.
1301 alloc_assoc
(int type
, const char *name
)
1305 if
((assoc
= malloc
(sizeof
(assoc_t
))) == NULL
) {
1306 warn
(gettext
(ERR_ASSOC_ALLOC
));
1309 (void) memset
(assoc
, 0, sizeof
(assoc_t
));
1310 assoc
->assoc_type
= type
;
1311 assoc
->assoc_name
= name
;
1316 * check_conf_name() ensures the the name of the system in the configuration
1317 * which is being manipulated matches the name of the system in the command.
1318 * If not, the command is terminated with an appropriate error message.
1321 check_conf_name
(cmd_t
*cmd
)
1327 if
((pe
= pool_conf_to_elem
(conf
)) == NULL
)
1328 die
(gettext
(ERR_GET_ELEMENT_DETAILS
),
1329 gettext
(CONFIGURATION
), "unknown", get_errstr
());
1332 if
((pv
= pool_value_alloc
()) == NULL
) {
1333 die
(gettext
(ERR_ALLOC_ELEMENT
), gettext
(RESOURCE
),
1337 if
(pool_get_property
(conf
, pe
, SYSTEM_NAME
, pv
)
1339 die
(gettext
(ERR_GET_PROPERTY
), gettext
(SYSTEM_NAME
),
1342 if
(pool_value_get_string
(pv
, &name
) == PO_FAIL
)
1343 die
(gettext
(ERR_GET_PROPERTY
), gettext
(SYSTEM_NAME
),
1346 if
(strcmp
(cmd
->cmd_tgt1
, name
) != 0) {
1347 die
(gettext
(ERR_WRONG_SYSTEM_NAME
), cmd
->cmd_tgt1
);
1349 pool_value_free
(pv
);
1353 * usage() display brief or verbose help for the poolcfg(1) command.
1359 (void) fprintf
(stderr
, gettext
(USAGE1
), cmdname
, cmdname
,
1362 (void) fprintf
(stderr
, gettext
(USAGE2
));
1367 * prop_list_walk() walks the property manipulation requests and either puts
1368 * or removes the property as appropriate.
1371 prop_list_walk
(cmd_t
*cmd
, pool_elem_t
*pe
)
1375 for
(prop
= cmd
->cmd_prop_list
; prop
!= NULL
; prop
= prop
->prop_next
) {
1376 switch
(prop
->prop_op
) {
1378 if
(pool_put_property
(conf
, pe
, prop
->prop_name
,
1379 prop
->prop_value
) != 0)
1380 die
(gettext
(ERR_PUT_PROPERTY
),
1381 prop
->prop_name
, get_errstr
());
1384 if
(pool_rm_property
(conf
, pe
, prop
->prop_name
) != 0)
1385 die
(gettext
(ERR_REMOVE_PROPERTY
),
1386 prop
->prop_name
, get_errstr
());
1393 * assoc_list_walk() walks the resource association requests and attempts
1394 * to associate the pool with the specified resource.
1397 assoc_list_walk
(cmd_t
*cmd
, pool_t
*pool
)
1401 for
(assoc
= cmd
->cmd_assoc_list
; assoc
!= NULL
;
1402 assoc
= assoc
->assoc_next
) {
1403 pool_resource_t
*resource
;
1405 switch
(assoc
->assoc_type
) {
1407 if
((resource
= pool_get_resource
(conf
,
1408 PSET
, assoc
->assoc_name
)) == NULL
)
1409 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(PSET
),
1410 assoc
->assoc_name
, get_errstr
());
1413 die
(gettext
(ERR_UNKNOWN_RESOURCE
),
1417 if
(pool_associate
(conf
, pool
, resource
) != 0)
1418 die
(gettext
(ERR_ASSOC_RESOURCE
), assoc
->assoc_name
,
1424 * transfer_list_walk() walks the component assign requests and attempts
1425 * to assign the component with the specified resource.
1428 transfer_list_walk
(cmd_t
*cmd
, pool_resource_t
*tgt
)
1432 for
(assoc
= cmd
->cmd_assoc_list
; assoc
!= NULL
;
1433 assoc
= assoc
->assoc_next
) {
1434 pool_component_t
*comp
;
1435 pool_resource_t
*src
;
1436 pool_component_t
*xfer
[2] = {NULL
};
1438 if
((comp
= get_cpu
(assoc
->assoc_name
)) == NULL
)
1439 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(CPU
),
1440 assoc
->assoc_name
, get_errstr
());
1441 if
((src
= pool_get_owning_resource
(conf
, comp
)) == NULL
)
1442 die
(gettext
(ERR_XFER_COMPONENT
), gettext
(COMPONENT
),
1443 assoc
->assoc_name
, cmd
->cmd_tgt1
, get_errstr
());
1445 if
(pool_resource_xtransfer
(conf
, src
, tgt
, xfer
) !=
1447 die
(gettext
(ERR_XFER_COMPONENT
), gettext
(COMPONENT
),
1448 assoc
->assoc_name
, cmd
->cmd_tgt1
, get_errstr
());
1453 * terminate() is invoked when poolcfg exits. It cleans up
1454 * configurations and closes the parser input stream.
1460 (void) pool_conf_close
(conf
);
1461 pool_conf_free
(conf
);
1464 (void) fclose
(yyin
);
1468 * get_cpu() takes the name of a CPU components and attempts to locate
1469 * the element with that name. If the name is not formatted correctly
1470 * (i.e. contains non-numeric characters) then the function terminates
1471 * execution. If the components cannot be uniquely identified by the
1472 * name, then NULL is returned.
1474 static pool_component_t
*
1475 get_cpu
(const char *name
)
1477 pool_component_t
**components
;
1480 pool_value_t
*vals
[3] = {NULL
};
1481 pool_component_t
*ret
;
1484 if
((vals
[0] = pool_value_alloc
()) == NULL
)
1486 if
((vals
[1] = pool_value_alloc
()) == NULL
) {
1487 pool_value_free
(vals
[0]);
1490 if
(pool_value_set_string
(vals
[0], "cpu") != PO_SUCCESS ||
1491 pool_value_set_name
(vals
[0], "type") != PO_SUCCESS
) {
1492 pool_value_free
(vals
[0]);
1493 pool_value_free
(vals
[1]);
1497 for
(c
= name
; *c
!= NULL
; c
++) {
1499 pool_value_free
(vals
[0]);
1500 pool_value_free
(vals
[1]);
1501 die
(gettext
(ERR_LOCATE_ELEMENT
), gettext
(CPU
),
1502 cmd
->cmd_tgt1
, gettext
("CPU id should only contain "
1506 sysid
= strtoll
(name
, NULL
, 0);
1507 if
(errno
== ERANGE || errno
== EINVAL
) {
1508 pool_value_free
(vals
[0]);
1509 pool_value_free
(vals
[1]);
1512 pool_value_set_int64
(vals
[1], sysid
);
1513 if
(pool_value_set_name
(vals
[1], CPU_SYSID
) != PO_SUCCESS
) {
1514 pool_value_free
(vals
[0]);
1515 pool_value_free
(vals
[1]);
1518 if
((components
= pool_query_components
(conf
, &nelem
, vals
)) ==
1520 pool_value_free
(vals
[0]);
1521 pool_value_free
(vals
[1]);
1526 pool_value_free
(vals
[0]);
1527 pool_value_free
(vals
[1]);
1530 pool_value_free
(vals
[0]);
1531 pool_value_free
(vals
[1]);
1532 ret
= components
[0];
1538 * process_min_max() ensures that "min" and "max" properties are
1539 * processed correctly by poolcfg. libpool enforces validity
1540 * constraints on these properties and so it's important that changes
1541 * to them are supplied to the library in the correct order.
1544 process_min_max
(pool_resource_t
*resource
)
1546 prop_t
*minprop
= NULL
;
1547 prop_t
*maxprop
= NULL
;
1551 * Before walking the list of properties, it has to be checked
1552 * to ensure there are no clashes between min and max. If
1553 * there are, then process these properties immediately.
1555 for
(prop
= cmd
->cmd_prop_list
; prop
!= NULL
; prop
= prop
->prop_next
) {
1558 if
((pos
= strstr
(prop
->prop_name
, min_suffix
)) != NULL
)
1559 if
(pos
== prop
->prop_name
+ strlen
(prop
->prop_name
)
1562 if
((pos
= strstr
(prop
->prop_name
, max_suffix
)) != NULL
)
1563 if
(pos
== prop
->prop_name
+ strlen
(prop
->prop_name
)
1567 if
(minprop
&& maxprop
) {
1569 uint64_t smin
, smax
, dmax
;
1572 pool_elem_t
*pe
= pool_resource_to_elem
(conf
, resource
);
1574 if
((pv
= pool_value_alloc
()) == NULL
)
1575 die
(gettext
(ERR_NOMEM
));
1577 (void) pool_get_property
(conf
, pe
, "type", pv
);
1578 (void) pool_value_get_string
(pv
, &type
);
1580 if
((prop_name
= malloc
(strlen
(type
) + strlen
(max_suffix
)
1582 die
(gettext
(ERR_NOMEM
));
1584 (void) sprintf
(prop_name
, "%s%s", type
, max_suffix
);
1585 (void) pool_get_property
(conf
, pe
, prop_name
, pv
);
1586 (void) pool_value_get_uint64
(pv
, &dmax
);
1588 (void) pool_value_get_uint64
(minprop
->prop_value
, &smin
);
1590 (void) pool_value_get_uint64
(maxprop
->prop_value
, &smax
);
1592 (void) pool_put_property
(conf
, pe
,
1593 minprop
->prop_name
, minprop
->prop_value
);
1595 (void) pool_put_property
(conf
, pe
,
1596 maxprop
->prop_name
, maxprop
->prop_value
);
1598 free
((void *)prop_name
);
1599 pool_value_free
(pv
);