1""" 2Support IPMI commands over LAN. This module does not talk to the local 3systems hardware through IPMI drivers. It uses a python module `pyghmi`. 4 5:depends: Python module pyghmi. 6 You can install pyghmi using pip: 7 8 .. code-block:: bash 9 10 pip install pyghmi 11 12:configuration: The following configuration defaults can be 13 define (pillar or config files): 14 15 .. code-block:: python 16 17 ipmi.config: 18 api_host: 127.0.0.1 19 api_user: admin 20 api_pass: apassword 21 api_port: 623 22 api_kg: None 23 24 Usage can override the config defaults: 25 26 .. code-block:: bash 27 28 salt-call ipmi.get_user api_host=myipmienabled.system 29 api_user=admin api_pass=pass 30 uid=1 31""" 32 33 34IMPORT_ERR = None 35try: 36 from pyghmi.ipmi import command 37 from pyghmi.ipmi.private import session 38except Exception as ex: # pylint: disable=broad-except 39 IMPORT_ERR = str(ex) 40 41__virtualname__ = "ipmi" 42 43 44def __virtual__(): 45 return (IMPORT_ERR is None, IMPORT_ERR) 46 47 48def _get_config(**kwargs): 49 """ 50 Return configuration 51 """ 52 config = { 53 "api_host": "localhost", 54 "api_port": 623, 55 "api_user": "admin", 56 "api_pass": "", 57 "api_kg": None, 58 "api_login_timeout": 2, 59 } 60 if "__salt__" in globals(): 61 config_key = "{}.config".format(__virtualname__) 62 config.update(__salt__["config.get"](config_key, {})) 63 for k in set(config) & set(kwargs): 64 config[k] = kwargs[k] 65 return config 66 67 68class _IpmiCommand: 69 o = None 70 71 def __init__(self, **kwargs): 72 config = _get_config(**kwargs) 73 self.o = command.Command( 74 bmc=config["api_host"], 75 userid=config["api_user"], 76 password=config["api_pass"], 77 port=config["api_port"], 78 kg=config["api_kg"], 79 ) 80 81 def __enter__(self): 82 return self.o 83 84 def __exit__(self, type, value, traceback): 85 if self.o: 86 self.o.ipmi_session.logout() 87 88 89class _IpmiSession: 90 o = None 91 92 def _onlogon(self, response): 93 if "error" in response: 94 raise Exception(response["error"]) 95 96 def __init__(self, **kwargs): 97 config = _get_config(**kwargs) 98 self.o = session.Session( 99 bmc=config["api_host"], 100 userid=config["api_user"], 101 password=config["api_pass"], 102 port=config["api_port"], 103 kg=config["api_kg"], 104 onlogon=self._onlogon, 105 ) 106 while not self.o.logged: 107 # override timeout 108 self.o.maxtimeout = config["api_login_timeout"] 109 self.o.wait_for_rsp(timeout=1) 110 self.o.maxtimeout = 5 111 112 def __enter__(self): 113 return self.o 114 115 def __exit__(self, type, value, traceback): 116 if self.o: 117 self.o.logout() 118 119 120def raw_command( 121 netfn, command, bridge_request=None, data=(), retry=True, delay_xmit=None, **kwargs 122): 123 """ 124 Send raw ipmi command 125 126 This allows arbitrary IPMI bytes to be issued. This is commonly used 127 for certain vendor specific commands. 128 129 :param netfn: Net function number 130 :param command: Command value 131 :param bridge_request: The target slave address and channel number for 132 the bridge request. 133 :param data: Command data as a tuple or list 134 :param kwargs: 135 - api_host=127.0.0.1 136 - api_user=admin 137 - api_pass=example 138 - api_port=623 139 - api_kg=None 140 141 :returns: dict -- The response from IPMI device 142 143 CLI Examples: 144 145 .. code-block:: bash 146 147 salt-call ipmi.raw_command netfn=0x06 command=0x46 data=[0x02] 148 # this will return the name of the user with id 2 in bytes 149 """ 150 with _IpmiSession(**kwargs) as s: 151 r = s.raw_command( 152 netfn=int(netfn), 153 command=int(command), 154 bridge_request=bridge_request, 155 data=data, 156 retry=retry, 157 delay_xmit=delay_xmit, 158 ) 159 return r 160 161 162def fast_connect_test(**kwargs): 163 """ 164 Returns True if connection success. 165 This uses an aggressive timeout value! 166 167 :param kwargs: 168 - api_host=127.0.0.1 169 - api_user=admin 170 - api_pass=example 171 - api_port=623 172 - api_kg=None 173 174 CLI Examples: 175 176 .. code-block:: bash 177 178 salt-call ipmi.fast_connect_test api_host=172.168.0.9 179 """ 180 try: 181 if "api_login_timeout" not in kwargs: 182 kwargs["api_login_timeout"] = 0 183 with _IpmiSession(**kwargs) as s: 184 # TODO: should a test command be fired? 185 # s.raw_command(netfn=6, command=1, retry=False) 186 return True 187 except Exception as e: # pylint: disable=broad-except 188 return False 189 return True 190 191 192def set_channel_access( 193 channel=14, 194 access_update_mode="non_volatile", 195 alerting=False, 196 per_msg_auth=False, 197 user_level_auth=False, 198 access_mode="always", 199 privilege_update_mode="non_volatile", 200 privilege_level="administrator", 201 **kwargs 202): 203 """ 204 Set channel access 205 206 :param channel: number [1:7] 207 208 :param access_update_mode: 209 - 'dont_change' = don't set or change Channel Access 210 - 'non_volatile' = set non-volatile Channel Access 211 - 'volatile' = set volatile (active) setting of Channel Access 212 213 :param alerting: 214 PEF Alerting Enable/Disable 215 216 - True = enable PEF Alerting 217 - False = disable PEF Alerting on this channel 218 (Alert Immediate command can still be used to generate alerts) 219 220 :param per_msg_auth: 221 Per-message Authentication 222 223 - True = enable 224 - False = disable Per-message Authentication. [Authentication required to 225 activate any session on this channel, but authentication not 226 used on subsequent packets for the session.] 227 228 :param user_level_auth: 229 User Level Authentication Enable/Disable 230 231 - True = enable User Level Authentication. All User Level commands are 232 to be authenticated per the Authentication Type that was 233 negotiated when the session was activated. 234 - False = disable User Level Authentication. Allow User Level commands to 235 be executed without being authenticated. 236 If the option to disable User Level Command authentication is 237 accepted, the BMC will accept packets with Authentication Type 238 set to None if they contain user level commands. 239 For outgoing packets, the BMC returns responses with the same 240 Authentication Type that was used for the request. 241 242 :param access_mode: 243 Access Mode for IPMI messaging (PEF Alerting is enabled/disabled 244 separately from IPMI messaging) 245 246 - disabled = disabled for IPMI messaging 247 - pre_boot = pre-boot only channel only available when system is 248 in a powered down state or in BIOS prior to start of boot. 249 - always = channel always available regardless of system mode. 250 BIOS typically dedicates the serial connection to the BMC. 251 - shared = same as always available, but BIOS typically leaves the 252 serial port available for software use. 253 254 :param privilege_update_mode: 255 Channel Privilege Level Limit. This value sets the maximum privilege 256 level that can be accepted on the specified channel. 257 258 - dont_change = don't set or change channel Privilege Level Limit 259 - non_volatile = non-volatile Privilege Level Limit according 260 - volatile = volatile setting of Privilege Level Limit 261 262 :param privilege_level: 263 Channel Privilege Level Limit 264 265 - reserved = unused 266 - callback 267 - user 268 - operator 269 - administrator 270 - proprietary = used by OEM 271 272 :param kwargs: 273 - api_host=127.0.0.1 274 - api_user=admin 275 - api_pass=example 276 - api_port=623 277 - api_kg=None 278 279 CLI Examples: 280 281 .. code-block:: bash 282 283 salt-call ipmi.set_channel_access privilege_level='administrator' 284 """ 285 with _IpmiCommand(**kwargs) as s: 286 return s.set_channel_access( 287 channel, 288 access_update_mode, 289 alerting, 290 per_msg_auth, 291 user_level_auth, 292 access_mode, 293 privilege_update_mode, 294 privilege_level, 295 ) 296 297 298def get_channel_access(channel=14, read_mode="non_volatile", **kwargs): 299 """ 300 :param kwargs:api_host='127.0.0.1' api_user='admin' api_pass='example' api_port=623 301 302 :param channel: number [1:7] 303 304 :param read_mode: 305 - non_volatile = get non-volatile Channel Access 306 - volatile = get present volatile (active) setting of Channel Access 307 308 :param kwargs: 309 - api_host=127.0.0.1 310 - api_user=admin 311 - api_pass=example 312 - api_port=623 313 - api_kg=None 314 315 Return Data 316 317 A Python dict with the following keys/values: 318 319 .. code-block:: python 320 321 { 322 alerting: 323 per_msg_auth: 324 user_level_auth: 325 access_mode:{ (ONE OF) 326 0: 'disabled', 327 1: 'pre_boot', 328 2: 'always', 329 3: 'shared' 330 } 331 privilege_level: { (ONE OF) 332 1: 'callback', 333 2: 'user', 334 3: 'operator', 335 4: 'administrator', 336 5: 'proprietary', 337 } 338 } 339 340 CLI Examples: 341 342 .. code-block:: bash 343 344 salt-call ipmi.get_channel_access channel=1 345 """ 346 with _IpmiCommand(**kwargs) as s: 347 return s.get_channel_access(channel) 348 349 350def get_channel_info(channel=14, **kwargs): 351 """ 352 Get channel info 353 354 :param channel: number [1:7] 355 :param kwargs: 356 - api_host=127.0.0.1 357 - api_user=admin 358 - api_pass=example 359 - api_port=623 360 - api_kg=None 361 362 Return Data 363 channel session supports 364 365 .. code-block:: none 366 367 - no_session: channel is session-less 368 - single: channel is single-session 369 - multi: channel is multi-session 370 - auto: channel is session-based (channel could alternate between 371 single- and multi-session operation, as can occur with a 372 serial/modem channel that supports connection mode auto-detect) 373 374 CLI Examples: 375 376 .. code-block:: bash 377 378 salt-call ipmi.get_channel_info 379 """ 380 with _IpmiCommand(**kwargs) as s: 381 return s.get_channel_info(channel) 382 383 384def set_user_access( 385 uid, 386 channel=14, 387 callback=True, 388 link_auth=True, 389 ipmi_msg=True, 390 privilege_level="administrator", 391 **kwargs 392): 393 """ 394 Set user access 395 396 :param uid: user number [1:16] 397 398 :param channel: number [1:7] 399 400 :param callback: 401 User Restricted to Callback 402 403 - False = User Privilege Limit is determined by the User Privilege Limit 404 parameter, below, for both callback and non-callback connections. 405 - True = User Privilege Limit is determined by the User Privilege Limit 406 parameter for callback connections, but is restricted to Callback 407 level for non-callback connections. Thus, a user can only initiate 408 a Callback when they 'call in' to the BMC, but once the callback 409 connection has been made, the user could potentially establish a 410 session as an Operator. 411 412 :param link_auth: User Link authentication enable/disable (used to enable 413 whether this user's name and password information will be used for link 414 authentication, e.g. PPP CHAP) for the given channel. Link 415 authentication itself is a global setting for the channel and is 416 enabled/disabled via the serial/modem configuration parameters. 417 418 :param ipmi_msg: User IPMI Messaging: (used to enable/disable whether 419 this user's name and password information will be used for IPMI 420 Messaging. In this case, 'IPMI Messaging' refers to the ability to 421 execute generic IPMI commands that are not associated with a 422 particular payload type. For example, if IPMI Messaging is disabled for 423 a user, but that user is enabled for activating the SOL 424 payload type, then IPMI commands associated with SOL and session 425 management, such as Get SOL Configuration Parameters and Close Session 426 are available, but generic IPMI commands such as Get SEL Time are 427 unavailable.) 428 429 :param privilege_level: 430 User Privilege Limit. (Determines the maximum privilege level that the 431 user is allowed to switch to on the specified channel.) 432 433 - callback 434 - user 435 - operator 436 - administrator 437 - proprietary 438 - no_access 439 440 :param kwargs: 441 - api_host=127.0.0.1 442 - api_user=admin 443 - api_pass=example 444 - api_port=623 445 - api_kg=None 446 447 CLI Examples: 448 449 .. code-block:: bash 450 451 salt-call ipmi.set_user_access uid=2 privilege_level='operator' 452 """ 453 with _IpmiCommand(**kwargs) as s: 454 return s.set_user_access( 455 uid, channel, callback, link_auth, ipmi_msg, privilege_level 456 ) 457 458 459def get_user_access(uid, channel=14, **kwargs): 460 """ 461 Get user access 462 463 :param uid: user number [1:16] 464 :param channel: number [1:7] 465 :param kwargs: 466 - api_host=127.0.0.1 467 - api_user=admin 468 - api_pass=example 469 - api_port=623 470 - api_kg=None 471 472 Return Data 473 474 .. code-block:: none 475 476 channel_info: 477 - max_user_count = maximum number of user IDs on this channel 478 - enabled_users = count of User ID slots presently in use 479 - users_with_fixed_names = count of user IDs with fixed names 480 access: 481 - callback 482 - link_auth 483 - ipmi_msg 484 - privilege_level: [reserved, callback, user, operator 485 administrator, proprietary, no_access] 486 487 CLI Examples: 488 489 .. code-block:: bash 490 491 salt-call ipmi.get_user_access uid=2 492 """ 493 ## user access available during call-in or callback direct connection 494 with _IpmiCommand(**kwargs) as s: 495 return s.get_user_access(uid, channel=channel) 496 497 498def set_user_name(uid, name, **kwargs): 499 """ 500 Set user name 501 502 :param uid: user number [1:16] 503 :param name: username (limit of 16bytes) 504 :param kwargs: 505 - api_host=127.0.0.1 506 - api_user=admin 507 - api_pass=example 508 - api_port=623 509 - api_kg=None 510 511 CLI Examples: 512 513 .. code-block:: bash 514 515 salt-call ipmi.set_user_name uid=2 name='steverweber' 516 """ 517 with _IpmiCommand(**kwargs) as s: 518 return s.set_user_name(uid, name) 519 520 521def get_user_name(uid, return_none_on_error=True, **kwargs): 522 """ 523 Get user name 524 525 :param uid: user number [1:16] 526 :param return_none_on_error: return None on error 527 :param kwargs: 528 - api_host=127.0.0.1 529 - api_user=admin 530 - api_pass=example 531 - api_port=623 532 - api_kg=None 533 534 CLI Examples: 535 536 .. code-block:: bash 537 538 salt-call ipmi.get_user_name uid=2 539 """ 540 with _IpmiCommand(**kwargs) as s: 541 return s.get_user_name(uid, return_none_on_error=True) 542 543 544def set_user_password(uid, mode="set_password", password=None, **kwargs): 545 """ 546 Set user password and (modes) 547 548 :param uid: id number of user. see: get_names_uid()['name'] 549 550 :param mode: 551 - disable = disable user connections 552 - enable = enable user connections 553 - set_password = set or ensure password 554 - test_password = test password is correct 555 :param password: max 16 char string 556 (optional when mode is [disable or enable]) 557 :param kwargs: 558 - api_host=127.0.0.1 559 - api_user=admin 560 - api_pass=example 561 - api_port=623 562 - api_kg=None 563 564 :return: 565 True on success 566 when mode = test_password, return False on bad password 567 568 CLI Example: 569 570 .. code-block:: bash 571 572 salt-call ipmi.set_user_password api_host=127.0.0.1 api_user=admin api_pass=pass 573 uid=1 password=newPass 574 salt-call ipmi.set_user_password uid=1 mode=enable 575 """ 576 with _IpmiCommand(**kwargs) as s: 577 s.set_user_password(uid, mode="set_password", password=password) 578 return True 579 580 581def get_health(**kwargs): 582 """ 583 Get Summarize health 584 585 This provides a summary of the health of the managed system. 586 It additionally provides an iterable list of reasons for 587 warning, critical, or failed assessments. 588 589 good health: {'badreadings': [], 'health': 0} 590 591 :param kwargs: 592 - api_host=127.0.0.1 593 - api_user=admin 594 - api_pass=example 595 - api_port=623 596 - api_kg=None 597 598 CLI Example: 599 600 .. code-block:: bash 601 602 salt-call ipmi.get_health api_host=127.0.0.1 api_user=admin api_pass=pass 603 """ 604 with _IpmiCommand(**kwargs) as s: 605 return s.get_health() 606 607 608def get_power(**kwargs): 609 """ 610 Get current power state 611 612 The response, if successful, should contain 'powerstate' key and 613 either 'on' or 'off' to indicate current state. 614 615 :param kwargs: 616 - api_host=127.0.0.1 617 - api_user=admin 618 - api_pass=example 619 - api_port=623 620 - api_kg=None 621 622 CLI Example: 623 624 .. code-block:: bash 625 626 salt-call ipmi.get_power api_host=127.0.0.1 api_user=admin api_pass=pass 627 """ 628 with _IpmiCommand(**kwargs) as s: 629 return s.get_power()["powerstate"] 630 631 632def get_sensor_data(**kwargs): 633 """ 634 Get sensor readings 635 636 Iterates sensor reading objects 637 638 :param kwargs: 639 - api_host=127.0.0.1 640 - api_user=admin 641 - api_pass=example 642 - api_port=623 643 - api_kg=None 644 645 CLI Example: 646 647 .. code-block:: bash 648 649 salt-call ipmi.get_sensor_data api_host=127.0.0.1 api_user=admin api_pass=pass 650 """ 651 import ast 652 653 with _IpmiCommand(**kwargs) as s: 654 data = {} 655 for reading in s.get_sensor_data(): 656 if reading: 657 r = ast.literal_eval(repr(reading)) 658 data[r.pop("name")] = r 659 return data 660 661 662def get_bootdev(**kwargs): 663 """ 664 Get current boot device override information. 665 666 Provides the current requested boot device. Be aware that not all IPMI 667 devices support this. Even in BMCs that claim to, occasionally the 668 BIOS or UEFI fail to honor it. This is usually only applicable to the 669 next reboot. 670 671 :param kwargs: 672 - api_host=127.0.0.1 673 - api_user=admin 674 - api_pass=example 675 - api_port=623 676 - api_kg=None 677 678 CLI Example: 679 680 .. code-block:: bash 681 682 salt-call ipmi.get_bootdev api_host=127.0.0.1 api_user=admin api_pass=pass 683 """ 684 with _IpmiCommand(**kwargs) as s: 685 return s.get_bootdev() 686 687 688def set_power(state="power_on", wait=True, **kwargs): 689 """ 690 Request power state change 691 692 :param name: 693 * power_on -- system turn on 694 * power_off -- system turn off (without waiting for OS) 695 * shutdown -- request OS proper shutdown 696 * reset -- reset (without waiting for OS) 697 * boot -- If system is off, then 'on', else 'reset' 698 699 :param ensure: If (bool True), do not return until system actually completes 700 requested state change for 300 seconds. 701 If a non-zero (int), adjust the wait time to the 702 requested number of seconds 703 :param kwargs: 704 - api_host=127.0.0.1 705 - api_user=admin 706 - api_pass=example 707 - api_port=623 708 - api_kg=None 709 710 :returns: dict -- A dict describing the response retrieved 711 712 CLI Examples: 713 714 .. code-block:: bash 715 716 salt-call ipmi.set_power state=shutdown wait=True 717 """ 718 if state is True or state == "power_on": 719 state = "on" 720 if state is False or state == "power_off": 721 state = "off" 722 with _IpmiCommand(**kwargs) as s: 723 return s.set_power(state, wait=wait) 724 725 726def set_bootdev(bootdev="default", persist=False, uefiboot=False, **kwargs): 727 """ 728 Set boot device to use on next reboot 729 730 :param bootdev: 731 - network: Request network boot 732 - hd: Boot from hard drive 733 - safe: Boot from hard drive, requesting 'safe mode' 734 - optical: boot from CD/DVD/BD drive 735 - setup: Boot into setup utility 736 - default: remove any IPMI directed boot device 737 request 738 739 :param persist: If true, ask that system firmware use this device 740 beyond next boot. Be aware many systems do not honor 741 this 742 743 :param uefiboot: If true, request UEFI boot explicitly. Strictly 744 speaking, the spec suggests that if not set, the system 745 should BIOS boot and offers no "don't care" option. 746 In practice, this flag not being set does not preclude 747 UEFI boot on any system I've encountered. 748 749 :param kwargs: 750 - api_host=127.0.0.1 751 - api_user=admin 752 - api_pass=example 753 - api_port=623 754 - api_kg=None 755 756 :returns: dict or True -- If callback is not provided, the response 757 758 CLI Examples: 759 760 .. code-block:: bash 761 762 salt-call ipmi.set_bootdev bootdev=network persist=True 763 """ 764 with _IpmiCommand(**kwargs) as s: 765 return s.set_bootdev(bootdev) 766 767 768def set_identify(on=True, duration=600, **kwargs): 769 """ 770 Request identify light 771 772 Request the identify light to turn off, on for a duration, 773 or on indefinitely. Other than error exceptions, 774 775 :param on: Set to True to force on or False to force off 776 :param duration: Set if wanting to request turn on for a duration 777 in seconds, None = indefinitely. 778 :param kwargs: 779 - api_host=127.0.0.1 780 - api_user=admin 781 - api_pass=example 782 - api_port=623 783 - api_kg=None 784 785 CLI Examples: 786 787 .. code-block:: bash 788 789 salt-call ipmi.set_identify 790 """ 791 with _IpmiCommand(**kwargs) as s: 792 return s.set_identify(on=on, duration=duration) 793 794 795def get_channel_max_user_count(channel=14, **kwargs): 796 """ 797 Get max users in channel 798 799 :param channel: number [1:7] 800 :param kwargs: 801 - api_host=127.0.0.1 802 - api_user=admin 803 - api_pass=example 804 - api_port=623 805 - api_kg=None 806 :return: int -- often 16 807 808 CLI Examples: 809 810 .. code-block:: bash 811 812 salt-call ipmi.get_channel_max_user_count 813 """ 814 access = get_user_access(channel=channel, uid=1, **kwargs) 815 return access["channel_info"]["max_user_count"] 816 817 818def get_user(uid, channel=14, **kwargs): 819 """ 820 Get user from uid and access on channel 821 822 :param uid: user number [1:16] 823 :param channel: number [1:7] 824 :param kwargs: 825 - api_host=127.0.0.1 826 - api_user=admin 827 - api_pass=example 828 - api_port=623 829 - api_kg=None 830 831 Return Data 832 833 .. code-block:: none 834 835 name: (str) 836 uid: (int) 837 channel: (int) 838 access: 839 - callback (bool) 840 - link_auth (bool) 841 - ipmi_msg (bool) 842 - privilege_level: (str)[callback, user, operatorm administrator, 843 proprietary, no_access] 844 845 CLI Examples: 846 847 .. code-block:: bash 848 849 salt-call ipmi.get_user uid=2 850 """ 851 name = get_user_name(uid, **kwargs) 852 access = get_user_access(uid, channel, **kwargs) 853 data = {"name": name, "uid": uid, "channel": channel, "access": access["access"]} 854 return data 855 856 857def get_users(channel=14, **kwargs): 858 """ 859 get list of users and access information 860 861 :param channel: number [1:7] 862 863 :param kwargs: 864 - api_host=127.0.0.1 865 - api_user=admin 866 - api_pass=example 867 - api_port=623 868 - api_kg=None 869 870 :return: 871 - name: (str) 872 - uid: (int) 873 - channel: (int) 874 - access: 875 - callback (bool) 876 - link_auth (bool) 877 - ipmi_msg (bool) 878 - privilege_level: (str)[callback, user, operatorm administrator, 879 proprietary, no_access] 880 881 CLI Examples: 882 883 .. code-block:: bash 884 885 salt-call ipmi.get_users api_host=172.168.0.7 886 """ 887 with _IpmiCommand(**kwargs) as c: 888 return c.get_users(channel) 889 890 891def create_user( 892 uid, 893 name, 894 password, 895 channel=14, 896 callback=False, 897 link_auth=True, 898 ipmi_msg=True, 899 privilege_level="administrator", 900 **kwargs 901): 902 """ 903 create/ensure a user is created with provided settings. 904 905 :param privilege_level: 906 User Privilege Limit. (Determines the maximum privilege level that 907 the user is allowed to switch to on the specified channel.) 908 * callback 909 * user 910 * operator 911 * administrator 912 * proprietary 913 * no_access 914 :param kwargs: 915 - api_host=127.0.0.1 916 - api_user=admin 917 - api_pass=example 918 - api_port=623 919 - api_kg=None 920 921 CLI Examples: 922 923 .. code-block:: bash 924 925 salt-call ipmi.create_user uid=2 name=steverweber api_host=172.168.0.7 api_pass=nevertell 926 """ 927 with _IpmiCommand(**kwargs) as c: 928 return c.create_user( 929 uid, name, password, channel, callback, link_auth, ipmi_msg, privilege_level 930 ) 931 932 933def user_delete(uid, channel=14, **kwargs): 934 """ 935 Delete user (helper) 936 937 :param uid: user number [1:16] 938 :param channel: number [1:7] 939 :param kwargs: 940 - api_host=127.0.0.1 941 - api_user=admin 942 - api_pass=example 943 - api_port=623 944 - api_kg=None 945 946 CLI Examples: 947 948 .. code-block:: bash 949 950 salt-call ipmi.user_delete uid=2 951 """ 952 with _IpmiCommand(**kwargs) as c: 953 return c.user_delete(uid, channel) 954