mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-22 03:32:04 +00:00
Merge branch 'master' into ZVM_XCAT_DEV
This commit is contained in:
commit
c012b45ec1
12
README.rst
12
README.rst
@ -8,7 +8,7 @@ Documentation
|
||||
|
||||
xCAT documentation is available at: http://xcat-docs.readthedocs.io/en/latest/
|
||||
|
||||
|docs_latest| |docs_2135| |docs_2134| |docs_2133| |docs_2132| |docs_2131| |docs_2130| |docs_212|
|
||||
|docs_latest| |docs_2137| |docs_2136| |docs_2135| |docs_2134| |docs_2133| |docs_2132| |docs_2131| |docs_2130| |docs_212|
|
||||
|
||||
Open Source License
|
||||
-------------------
|
||||
@ -22,6 +22,16 @@ Developers
|
||||
Developers and prospective contributors are encouraged to read the `Developers Guide <http://xcat-docs.readthedocs.io/en/latest/developers/>`_
|
||||
In particular the `GitHub <http://xcat-docs.readthedocs.io/en/latest/developers/github/>`_ related subsection.
|
||||
|
||||
.. |docs_2137| image:: https://readthedocs.org/projects/xcat-docs/badge/?version=2.13.7
|
||||
:alt: 2.13.7 documentation status
|
||||
:scale: 100%
|
||||
:target: http://xcat-docs.readthedocs.io/en/2.13.7/
|
||||
|
||||
.. |docs_2136| image:: https://readthedocs.org/projects/xcat-docs/badge/?version=2.13.6
|
||||
:alt: 2.13.6 documentation status
|
||||
:scale: 100%
|
||||
:target: http://xcat-docs.readthedocs.io/en/2.13.6/
|
||||
|
||||
.. |docs_2135| image:: https://readthedocs.org/projects/xcat-docs/badge/?version=2.13.5
|
||||
:alt: 2.13.5 documentation status
|
||||
:scale: 100%
|
||||
|
@ -524,7 +524,7 @@ __EOF__
|
||||
FILES_PATH="files"
|
||||
FRS="/var/www/${SERVER}/${FILES_PATH}"
|
||||
APT_DIR="${FRS}/xcat"
|
||||
APT_REPO_DIR="${APT_DIR}/repos/apt"
|
||||
APT_REPO_DIR="${APT_DIR}/repos/apt/devel"
|
||||
|
||||
# Decide whether to upload the xcat-dep package or NOT (default is to NOT upload xcat-dep
|
||||
if [ "$UP" != "1" ]; then
|
||||
|
@ -225,7 +225,7 @@ if [ "$OSNAME" == "AIX" ]; then
|
||||
else
|
||||
# Linux
|
||||
SYSGRP=root
|
||||
YUM=yum
|
||||
YUM=yum/devel
|
||||
FRSDIR='2.x_Linux'
|
||||
fi
|
||||
chgrp -R -h $SYSGRP *
|
||||
|
@ -6,6 +6,7 @@ Advanced Topics
|
||||
|
||||
chain/index.rst
|
||||
cluster_maintenance/index.rst
|
||||
migration/index.rst
|
||||
confluent/index.rst
|
||||
docker/index.rst
|
||||
domain_name_resolution/index.rst
|
||||
|
7
docs/source/advanced/migration/index.rst
Normal file
7
docs/source/advanced/migration/index.rst
Normal file
@ -0,0 +1,7 @@
|
||||
Migrate xCat Management node
|
||||
============================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
migration.rst
|
189
docs/source/advanced/migration/migration.rst
Normal file
189
docs/source/advanced/migration/migration.rst
Normal file
@ -0,0 +1,189 @@
|
||||
xCAT Management Node Migration
|
||||
==============================
|
||||
|
||||
This document describes how to migrate xCAT Management node to a new node. The following example describes a typical scenario, this example is verified on redhat7.3.
|
||||
|
||||
#. Initially, the first xcat management node is active, and the second node is passive.
|
||||
#. Backup all useful xCAT data from xCAT Management node to back-up server at regular intervals.
|
||||
#. When the first xCAT management node is broken, use backup to restore original xCAT data to the second node with the same host name and ip.
|
||||
|
||||
Backup Old xCAT Management Node
|
||||
-------------------------------
|
||||
|
||||
Backup xCAT management node data to backup server:
|
||||
|
||||
1.1 Backup xCAT important files and directories:
|
||||
|
||||
#. Get ``installdir`` from ``site`` table, backup ``installdir`` directory,
|
||||
in this case, back up ``install`` directory: ::
|
||||
|
||||
lsdef -t site clustersite -i installdir
|
||||
Object name: clustersite
|
||||
installdir=/install
|
||||
|
||||
#. Backup these two xCAT directories: ::
|
||||
|
||||
~/.xcat
|
||||
/etc/xcat
|
||||
|
||||
**Notes**: backing up ``~/.xcat`` is for all users who have xCAT client certs.
|
||||
|
||||
#. If there are customized files and directories for ``otherpkgdir``, ``pkgdir``, ``pkglist`` or ``template`` in some `osimage` definitions, backup these files and directories. for example: ::
|
||||
|
||||
lsdef -t osimage customized_rhels7.4-x86_64-install-compute -i otherpkgdir,pkgdir,pkglist,template
|
||||
Object name: customized_rhels7.4-x86_64-install-compute
|
||||
otherpkgdir=/<customized_dir>/post/otherpkgs/rhels7.4/x86_64
|
||||
pkgdir=/<customized_pkgdir>/rhels7.4/x86_64
|
||||
pkglist=/<customized_pkglist_dir>/compute.rhels7.pkglist
|
||||
template=/<customized_temp_dir>/compute.rhels7.tmpl
|
||||
|
||||
1.2 Backup ssh related files: ::
|
||||
|
||||
/etc/ssh
|
||||
~/.ssh
|
||||
|
||||
1.3 Backup host files: ::
|
||||
|
||||
/etc/resolv.conf
|
||||
/etc/hosts
|
||||
/etc/passwd
|
||||
/etc/group
|
||||
|
||||
1.4 Backup yum resource files: ::
|
||||
|
||||
/etc/yum.repos.d
|
||||
|
||||
1.5 Backup conserver conf files: ::
|
||||
|
||||
/etc/conserver.cf
|
||||
|
||||
1.6 Backup DNS related files: ::
|
||||
|
||||
/etc/named
|
||||
/etc/named.conf
|
||||
/etc/named.iscdlv.key
|
||||
/etc/named.root.key
|
||||
/etc/rndc.key
|
||||
/etc/sysconfig/named
|
||||
/var/named
|
||||
|
||||
1.7 Backup dhcp files: ::
|
||||
|
||||
/etc/dhcp
|
||||
/var/lib/dhcpd
|
||||
/etc/sysconfig/dhcpd
|
||||
/etc/sysconfig/dhcpd6
|
||||
|
||||
1.8 Backup apache: ::
|
||||
|
||||
/etc/httpd
|
||||
/var/www
|
||||
|
||||
1.9 Backup tftp files: ::
|
||||
|
||||
/tftpboot
|
||||
|
||||
1.10 Backup NTP configure file: ::
|
||||
|
||||
/etc/ntp.conf
|
||||
|
||||
1.11 Backup database configure files (optional):
|
||||
|
||||
* **[PostgreSQL]** ::
|
||||
|
||||
/var/lib/pgsql/data/pg_hba.conf
|
||||
/var/lib/pgsql/data/postgresql.conf
|
||||
|
||||
1.12 Backup NFS (optional): ::
|
||||
|
||||
/etc/exports
|
||||
/var/lib/nfs
|
||||
/etc/sysconfig/nfs
|
||||
|
||||
1.13 (optional)
|
||||
|
||||
Besides the files mentioned above, there may be some additional customization files and production files that need to be backup, depending on your local unique requirements. Here are some example files that can be considered: ::
|
||||
|
||||
/.profile
|
||||
/.rhosts
|
||||
/etc/auto_master
|
||||
/etc/auto/maps/auto.u
|
||||
/etc/motd
|
||||
/etc/security/limits
|
||||
/etc/netscvc.conf
|
||||
/etc/inetd.conf
|
||||
/etc/security/passwd
|
||||
/etc/security/group
|
||||
/etc/services
|
||||
/etc/inittab(andmore)
|
||||
|
||||
1.14 Backup the xCAT database tables for the current configuration, using command: ::
|
||||
|
||||
dumpxCATdb -p <your_backup_dir>
|
||||
|
||||
1.15 Save all installed xCAT RPM names into a file: ::
|
||||
|
||||
rpm -qa|grep -i xCAT > xcat_rpm_names
|
||||
|
||||
1.16 (Optional) Find customization made to files installed from packages, backup these files. For example ::
|
||||
|
||||
rpm -q --verify -a conserver-xcat
|
||||
rpm -q --verify -a xCAT-server
|
||||
rpm -q --verify -a syslinux-xcat
|
||||
rpm -q --verify -a xCAT-client
|
||||
rpm -q --verify -a xCAT
|
||||
|
||||
|
||||
Restore xCAT management node
|
||||
----------------------------
|
||||
|
||||
2.1 Power off old xCAT management server before configuring new xCAT management server
|
||||
|
||||
2.2 Configure new xCAT management server using the same ip and hostname as old xCAT management server. Configure the same additional network for hardware management network if needed, for example, bmc network or hmc network. xCAT management server setup refer to :doc:`Prepare the Management Node <../../guides/install-guides/yum/prepare_mgmt_node>`
|
||||
|
||||
2.3 Overwrite files/directories methioned in above 1.2, 1.3, 1.4 from backup server to new xCAT management server
|
||||
|
||||
2.4 Download xcat-core and xcat-dep tar ball, then install xCAT in new xCAT management server, refer to :doc:`install xCAT <../../guides/install-guides/yum/install>`
|
||||
|
||||
2.5 Use ``rpm -qa|grep -i xCAT`` to list all xCAT RPMs in new xCAT management node, compare these RPMs base name with those in ``xcat_rpm_names`` from above 1.15. If some RPMs are missing, use ``yum install <rpm_package_basename>`` to install missing RPMs.
|
||||
|
||||
2.6 If use ``MySQL``/``MariaDB``/``PostgreSQL``, migrate xCAT to use ``MySQL/MariaDB/PostgreSQL`` refer to :doc:`Configure a Database <../hierarchy/databases/index>`
|
||||
|
||||
2.7 To restore the xCAT database
|
||||
|
||||
a. Restore xCAT database from the ``/dbbackup/db`` directory without ``auditlog`` and ``eventlog``, enter: ::
|
||||
|
||||
restorexCATdb -p /dbbackup/db
|
||||
|
||||
b. Restore the xCAT database including ``auditlog`` and ``eventlog`` from the ``/dbbackup/db`` directory, enter: ::
|
||||
|
||||
restorexCATdb -a -p /dbbackup/db
|
||||
|
||||
c. (optinal) Overwrite files in above 1.11, restart ``PostgreSQL``: ::
|
||||
|
||||
service postgresql restart
|
||||
|
||||
2.8 Overwrite remaining files/directories methioned in above 1.1, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.12; If needed, check if files exist based on above 1.13 and 1.16.
|
||||
|
||||
2.9 Verify xCAT: ::
|
||||
|
||||
tabdump site
|
||||
|
||||
2.10 Restart ``named``, use ``nslookup`` to check ``DNS``: ::
|
||||
|
||||
service named restart
|
||||
nslookup <cn1>
|
||||
|
||||
2.11 Restart ``conserver``, use ``rcons`` to check console: ::
|
||||
|
||||
service conserver restart
|
||||
rcons <cn1>
|
||||
|
||||
2.12 Configure DHCP: ::
|
||||
|
||||
makedhcp -n
|
||||
makedhcp -a
|
||||
|
||||
2.13 Restart ``httpd`` for REST API, for more information refer to :doc:`Rest API<../../../advanced/restapi/index>`: ::
|
||||
|
||||
service httpd restart
|
@ -10,3 +10,4 @@ This documentation will focus on installing the Cumulus Network Operating System
|
||||
prepare.rst
|
||||
install.rst
|
||||
manage.rst
|
||||
upgrade.rst
|
||||
|
@ -78,6 +78,8 @@ Validate the ssh keys are correctly configured by running a ``xdsh`` command: ::
|
||||
xdsh frame01sw1 uptime
|
||||
|
||||
|
||||
.. _activate-the-license:
|
||||
|
||||
Activate the License
|
||||
--------------------
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
Switch Management
|
||||
=================
|
||||
|
||||
VLAN Configuration
|
||||
------------------
|
||||
Switch Port and VLAN Configuration
|
||||
----------------------------------
|
||||
|
||||
xCAT ships a simple configuration script that will set all the ports on the switch to be part of VLAN 1. See the Cumulus Networks documentation for more information regarding advanced networking configuration. ::
|
||||
xCAT expects the configuration for the front-panel ports to be located at ``/etc/network/interfaces.d/xCAT.intf`` on the switch. The ``configinterface`` postscript can download an interface configuration file from the management node. Place the configuration file in the directory ``/install/custom/sw_os/cumulus/interface/`` on the management node. It will first look for a file named the same as the switch's hostname, followed by the name of each group, followed by the word 'default'. If the postscript cannot find a configuration file on the management node, it will set all the ports on the switch to be part of VLAN 1. See the Cumulus Networks documentation for more information regarding advanced networking configuration. ::
|
||||
|
||||
updatenode <switch> -P configinterface
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
Cumulus OS upgrade
|
||||
==================
|
||||
|
||||
The Cumulus OS on the ONIE switches can be upgraded in 2 ways:
|
||||
|
||||
* Upgrade only the changed packages, using ``apt-get update`` and ``apt-get upgrade``. If the ONIE switches has internet access, this is the preferred method, otherwise, you need to build up a local cumulus mirror in the cluster.
|
||||
|
||||
Since in a typical cluster setup, the switches usually do not have internet access, you can create a local mirror on the server which has internet access and can be reached from the switches, the steps are ::
|
||||
|
||||
mkdir -p /install/mirror/cumulus
|
||||
cd /install/mirror/cumulus
|
||||
#the wget might take a long time, it will be better if you can set up
|
||||
#a cron job to sync the local mirror with upstream
|
||||
wget -m --no-parent http://repo3.cumulusnetworks.com/repo/
|
||||
|
||||
then compose a ``sources.list`` file on MN like this(take 172.21.253.37 as ip address of the local mirror server) ::
|
||||
|
||||
#cat /tmp/sources.list
|
||||
deb http://172.21.253.37/install/mirror/cumulus/repo3.cumulusnetworks.com/repo CumulusLinux-3 cumulus upstream
|
||||
deb-src http://172.21.253.37/install/mirror/cumulus/repo3.cumulusnetworks.com/repo CumulusLinux-3 cumulus upstream
|
||||
|
||||
deb http://172.21.253.37/install/mirror/cumulus/repo3.cumulusnetworks.com/repo CumulusLinux-3-security-updates cumulus upstream
|
||||
deb-src http://172.21.253.37/install/mirror/cumulus/repo3.cumulusnetworks.com/repo CumulusLinux-3-security-updates cumulus upstream
|
||||
|
||||
deb http://172.21.253.37/install/mirror/cumulus/repo3.cumulusnetworks.com/repo CumulusLinux-3-updates cumulus upstream
|
||||
deb-src http://172.21.253.37/install/mirror/cumulus/repo3.cumulusnetworks.com/repo CumulusLinux-3-updates cumulus upstream
|
||||
|
||||
distribute the ``sources.list`` file to the switches to upgrade with ``xdcp``, take "switch1" as an example here ::
|
||||
|
||||
xdcp switch1 /tmp/sources.list /etc/apt/sources.list
|
||||
|
||||
then invoke ``apt-get update`` and ``apt-get install`` on the switches to start package upgrade, a reboot might be needed after upgrading ::
|
||||
|
||||
xdsh switch1 'apt-get update && apt-get upgrade && reboot'
|
||||
|
||||
check the `/etc/os-release` file to make sure the Cumulus OS has been upgraded ::
|
||||
|
||||
cat /etc/os-release
|
||||
|
||||
|
||||
|
||||
* Performe a binary (full image) install of the new version, using ONIE. If you expect to upgrade between major versions or if you have the binary image to upgrade to, this way is the recommended one. Make sure to backup your data and configuration files because binary install will erase all the configuration and data on the switch.
|
||||
|
||||
The steps to perform a binary (full image) install of the new version are:
|
||||
|
||||
1) place the binary image "cumulus-linux-3.4.1.bin" under ``/install`` directory on MN("172.21.253.37") ::
|
||||
|
||||
mkdir -p /install/onie/
|
||||
cp cumulus-linux-3.4.1.bin /install/onie/
|
||||
|
||||
2) invoke the upgrade on switches with ``xdsh`` ::
|
||||
|
||||
xdsh switch1 "/usr/cumulus/bin/onie-install -a -f -i http://172.21.253.37/install/onie/cumulus-linux-3.4.1.bin && reboot"
|
||||
|
||||
The full upgrade process might cost 30 min, you can ping the switch with ``ping switch1`` to check whether it finishes upgrade.
|
||||
|
||||
3) After upgrading, the license should be installed, see :ref:`Activate the License <activate-the-license>` for detailed steps.
|
||||
|
||||
4) Restore your data and configuration files on the switch.
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ author = u'IBM Corporation'
|
||||
# The short X.Y version.
|
||||
version = '2'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '2.12'
|
||||
release = '2.13.6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -95,6 +95,63 @@ Using easy regular expression support you would put this in the hosts table. ::
|
||||
In the easy regx example, the expression only has the 2nd part of the expression from the previous example. xCAT will evaluate the node name, matching the number part of the node name, and create the 1st part of the expression . The 2nd part supplied is what value to give the ip attribute. The resulting output is the same.
|
||||
|
||||
|
||||
Regular Expression Helper Functions
|
||||
-----------------------------------
|
||||
|
||||
xCAT provides several functions that can simplify regular expressions.
|
||||
|
||||
\ **a2idx** ASCII Character to Index\
|
||||
Usage: ``a2idx(character)``
|
||||
|
||||
Turns a single character into a 1-indexed index. ‘a’ maps to 1 and ‘z’ maps to 26.
|
||||
|
||||
\ **a2zidx** ASCII Character to 0-Index\
|
||||
Usage: ``a2zidx(character)``
|
||||
|
||||
Turns a single character into a 0-indexed index. ‘a’ maps to 0 and ‘z’ maps to 25.
|
||||
|
||||
\ **dim2idx** Dimensions to Index\
|
||||
Usage: ``dim2idx(value, [count, value...])``
|
||||
|
||||
Converts dimensions (such as row, column, chassis, etc) into an index. An example system consists of 8 racks, two rows with four columns each.
|
||||
|
||||
+-----------+-----------+-----------+-----------+
|
||||
| row1-col1 | row1-col2 | row1-col3 | row1-col4 |
|
||||
+-----------+-----------+-----------+-----------+
|
||||
| row2-col1 | row2-col2 | row2-col3 | row2-col4 |
|
||||
+-----------+-----------+-----------+-----------+
|
||||
To obtain the rack index, use ``|row(\d+)-col(\d+)|(dim2idx($1, 4, $2))|``. This maps the racks to:
|
||||
|
||||
+---+---+---+---+
|
||||
| 1 | 2 | 3 | 4 |
|
||||
+---+---+---+---+
|
||||
| 5 | 6 | 7 | 8 |
|
||||
+---+---+---+---+
|
||||
Note that the size of the highest dimension (2 rows) is not needed, and all values are one-indexed.
|
||||
|
||||
If each rack contains 20 nodes, use ``|row(\d+)-col(\d+)-node(\d+)|(dim2idx($1, 4, $2, 20, $3)`` to determine a node index (useful for determining IP addresses).
|
||||
|
||||
\ **skip** Skip indices\
|
||||
Usage: ``skip(index, skiplist)``
|
||||
|
||||
Return an index with certain values skipped. The skip list uses the format ``start[:count][,start[:count]...]``. Using the example above, to skip racks 3 and 4, use:
|
||||
|
||||
``|row(\d+)-col(\d+)|(skip(dim2idx($1, 4, $2),'3:2')|``
|
||||
|
||||
The result would be:
|
||||
|
||||
+---+---+---+---+
|
||||
| 1 | 2 | | |
|
||||
+---+---+---+---+
|
||||
| 3 | 4 | 5 | 6 |
|
||||
+---+---+---+---+
|
||||
|
||||
\ **ipadd** Add to an IP address\
|
||||
Usage: ``ipadd(octet1, octet2, octet3, octet4, toadd, skipstart, skipend)``
|
||||
|
||||
This function is useful when you need to cross octets. Optionally skip addresses at the start and end of octets (like .0 or .255 - technically those are valid IP addresses, but sometimes software makes poor assumptions about which broadcast and gateway addresses).
|
||||
|
||||
|
||||
Verify your regular expression
|
||||
------------------------------
|
||||
|
||||
|
@ -0,0 +1,85 @@
|
||||
Enabling the localdisk Option
|
||||
-----------------------------
|
||||
|
||||
``Note``: You can skip this section if not using the ``localdisk`` option in your litefile table.
|
||||
|
||||
Several things need to be done to enable the 'localdisk' support:
|
||||
|
||||
Define how to partition the local disk
|
||||
``````````````````````````````````````
|
||||
|
||||
When a node is deployed, the local hard disk needs to be partitioned and formatted before it can be used. This section explains how provide a configuration file that tells xCAT to partition a local disk and make it ready to use for the directories listed in the litefile table with the ``localdisk`` option.
|
||||
|
||||
The configuration file needs to be specified in the ``partitionfile`` attribute of the osimage definition. The configuration file includes several parts:
|
||||
|
||||
* Global parameters to control enabling or disabling the function
|
||||
* [disk] part to control the partitioning of the disk
|
||||
* [localspace] part to control which partition will be used to store the localdisk directories listed in the litefile table
|
||||
* [swapspace] part to control the enablement of the swap space for the node.
|
||||
|
||||
An example localdisk configuration file: ::
|
||||
|
||||
enable=yes
|
||||
enablepart=no
|
||||
|
||||
[disk]
|
||||
dev=/dev/sdb
|
||||
clear=yes
|
||||
parts=100M-200M,1G-2G
|
||||
|
||||
[disk]
|
||||
dev=/dev/sda
|
||||
clear=yes
|
||||
parts=10,20,30
|
||||
|
||||
[disk]
|
||||
dev=/dev/sdc
|
||||
clear=yes
|
||||
parts=10,20,30
|
||||
|
||||
[localspace]
|
||||
dev=/dev/sda1
|
||||
fstype=ext3
|
||||
|
||||
[swapspace]
|
||||
dev=/dev/sda2
|
||||
|
||||
The two global parameters ``enable`` and ``enablepart`` can be used to control the enabling/disabling of the functions:
|
||||
|
||||
* enable: The localdisk feature only works when ``enable`` is set to *yes*. If it is set to *no*, the localdisk configuration will not be run.
|
||||
* enablepart: The partition action (refer to the ``[disk]`` section) will be run only when ``enablepart=yes``.
|
||||
|
||||
The ``[disk]`` section is used to configure how to partition a hard disk:
|
||||
|
||||
* dev: The path of the device file.
|
||||
* clear: If set to ``yes`` it will clear all the existing partitions on this disk.
|
||||
* fstype: The file system type for the new created partitions. ``ext3`` is the default value if not set.
|
||||
* parts: A comma separated list of space ranges, one for each partition that will be created on the device. The valid format for each space range is ``<startpoint>-<endpoint>`` or ``<percentage of the disk>``. For example, you could set it to ``100M-10G`` or ``50``. If you set it to ``50``, that means 50% of the disk space will be assigned to that partition.
|
||||
|
||||
The ``[localspace]`` section is used to specify which partition will be used as local storage for the node.
|
||||
|
||||
* dev: The path of the partition.
|
||||
* fstype: The file system type on the partition.
|
||||
|
||||
the ``[swapspace]`` section is used to configure the swap space for the statelite node.
|
||||
|
||||
* dev: The path of the partition file which will be used as the swap space.
|
||||
|
||||
To enable the local disk capability, create the configuration file (for example in ``/install/custom``) and set the path in the partitionfile attribute for the osimage: ::
|
||||
|
||||
chdef -t osimage partitionfile=/install/custom/cfglocaldisk
|
||||
|
||||
Now all nodes that use this osimage (i.e. have their provmethod attribute set to this osimage definition name), will have its local disk configured.
|
||||
|
||||
Configure the files in the litefile table
|
||||
`````````````````````````````````````````
|
||||
|
||||
For the files/directories that you would like xCAT to store on the local disk, add an entry in the litefile table like this: ::
|
||||
|
||||
"ALL","/tmp/","localdisk",,
|
||||
|
||||
``Note``: you do not need to specify the swap space in the litefile table. Just putting it in the partitionfile config file is enough.
|
||||
|
||||
Add an entry in policy table to permit the running of the ``getpartitioin`` command from the node ::
|
||||
|
||||
chtab priority=7.1 policy.commands=getpartition policy.rule=allow
|
@ -31,8 +31,13 @@ Define attributes in the ``nics`` table
|
||||
chdef cn1 nicips.bond0.1=40.0.0.1 nictypes.bond0.1=vlan
|
||||
|
||||
#. Define ``nicnetworks`` for ``bond0.1`` ::
|
||||
|
||||
chdef cn1 nicnetworks.bond0.1=net40
|
||||
|
||||
#. Define ``nichostnamesuffixes`` for ``bond0.1`` in case ``makehosts`` to update ``/etc/hosts``, since the value for ``nichostnamesuffixes`` cannot contain ".", other characters are recommended instead of ".", like following: ::
|
||||
|
||||
chdef cn1 nichostnamesuffixes.bond0.1=-bond0-1
|
||||
|
||||
Enable ``confignetwork`` to configure bridge
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -31,6 +31,10 @@ Define attributes in the ``nics`` table
|
||||
|
||||
chdef cn1 nicnetworks.eth0.6=net60 nicnetworks.eth0.7=net70
|
||||
|
||||
#. Define ``nichostnamesuffixes`` for ``eth0.6`` and ``eth0.7`` in case ``makehosts`` to update ``/etc/hosts``, since the value for ``nichostnamesuffixes`` cannot contain ".", other characters are recommended instead of ".", like following: ::
|
||||
|
||||
chdef cn1 nichostnamesuffixes.eth0.6=-eth0-6 nichostnamesuffixes.eth0.7=-eth0-7
|
||||
|
||||
Enable ``confignetwork`` to configure VLAN
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -2,7 +2,7 @@ Manage Virtual Machine (VM)
|
||||
============================
|
||||
|
||||
|
||||
Now the MowerKVM hypervisor "kvmhost1" is ready, this section introduces the VM management in xCAT, including examples on how to create, remove and clone VMs.
|
||||
Now the PowerKVM hypervisor "kvmhost1" is ready, this section introduces the VM management in xCAT, including examples on how to create, remove and clone VMs.
|
||||
|
||||
Create Virtual Machine
|
||||
----------------------
|
||||
@ -82,7 +82,27 @@ After the VM object is created, several key attributes need to be specified with
|
||||
|
||||
chtab node=vm1 vm.vidpassword=abc123
|
||||
|
||||
10. Set **netboot** attribute
|
||||
10. (optional)For assigning PCI devices to the VM, set **othersettings** value: ::
|
||||
|
||||
chtab node=vm1 vm.othersettings="devpassthrough:0000:01:00.2"
|
||||
|
||||
Or: ::
|
||||
|
||||
chtab node=vm1 vm.othersettings="devpassthrough:pci_0000_01_00_2"
|
||||
|
||||
Take assigning SR-IOV VFs to the VM as an example:
|
||||
|
||||
* Use ``lspci`` to get VFs PCI from hypervisor: ::
|
||||
|
||||
lspci|grep -i "Virtual Function"
|
||||
0000:01:00.1 Infiniband controller: Mellanox Technologies MT27700 Family [ConnectX-4 Virtual Function]
|
||||
0000:01:00.2 Infiniband controller: Mellanox Technologies MT27700 Family [ConnectX-4 Virtual Function]
|
||||
|
||||
* Set the VFs PCI into ``vm`` table on MN: ::
|
||||
|
||||
chtab node=vm1 vm.othersettings="devpassthrough:0000:01:00.1,0000:01:00.2"
|
||||
|
||||
11. Set **netboot** attribute
|
||||
|
||||
* **[x86_64]** ::
|
||||
|
||||
|
@ -12,7 +12,7 @@ The following example outlines the MTMS based hardware discovery for a single IP
|
||||
+------------------------------+------------+
|
||||
| Hostname | cn01 |
|
||||
+------------------------------+------------+
|
||||
| IP address | 10.1.2.1 |
|
||||
| IP address | 10.0.101.1 |
|
||||
+------------------------------+------------+
|
||||
|
||||
The BMC IP address is obtained by the open range dhcp server and the plan in this scenario is to change the IP address for the BMC to a static IP address in a different subnet than the open range addresses. The static IP address in this example is in the same subnet as the open range to simplify the networking configuration on the xCAT management node.
|
||||
@ -20,9 +20,9 @@ The BMC IP address is obtained by the open range dhcp server and the plan in thi
|
||||
+------------------------------+------------+
|
||||
| BMC Information | Value |
|
||||
+==============================+============+
|
||||
| IP address - dhcp | 172.30.0.1 |
|
||||
| IP address - dhcp | 50.0.100.1 |
|
||||
+------------------------------+------------+
|
||||
| IP address - static | 172.20.2.1 |
|
||||
| IP address - static | 50.0.101.1 |
|
||||
+------------------------------+------------+
|
||||
|
||||
#. Detect the BMCs and add the node definitions into xCAT.
|
||||
@ -44,9 +44,9 @@ The BMC IP address is obtained by the open range dhcp server and the plan in thi
|
||||
|
||||
Use the ``bmcdiscover`` command to help discover the nodes over an IP range and easily create a starting file to define the compute nodes into xCAT.
|
||||
|
||||
To discover the compute nodes for the BMCs with an IP address of 172.30.0.1, use the command: ::
|
||||
To discover the compute nodes for the BMCs with an IP address of 50.0.100.1, use the command: ::
|
||||
|
||||
bmcdiscover --range 172.30.0.1 -z > predefined.stanzas
|
||||
bmcdiscover --range 50.0.100.1 -z > predefined.stanzas
|
||||
|
||||
The discovered nodes have the naming convention: node-<*model-type*>-<*serial-number*> ::
|
||||
|
||||
@ -54,7 +54,7 @@ The BMC IP address is obtained by the open range dhcp server and the plan in thi
|
||||
node-8247-22l-10112ca:
|
||||
objtype=node
|
||||
groups=all
|
||||
bmc=172.30.0.1
|
||||
bmc=50.0.100.1
|
||||
cons=ipmi
|
||||
mgt=ipmi
|
||||
mtm=8247-22L
|
||||
@ -73,7 +73,7 @@ The BMC IP address is obtained by the open range dhcp server and the plan in thi
|
||||
|
||||
#. Add a ``ip`` attribute and give it the compute node IP address: ::
|
||||
|
||||
ip=10.1.2.1
|
||||
ip=10.0.101.1
|
||||
|
||||
#. Remove ``nodetype`` and ``hwtype`` if defined in the ``predefined.stanza``.
|
||||
|
||||
@ -86,13 +86,16 @@ The BMC IP address is obtained by the open range dhcp server and the plan in thi
|
||||
cn01:
|
||||
objtype=node
|
||||
groups=all
|
||||
bmc=172.30.0.1
|
||||
bmc=50.0.100.1
|
||||
cons=ipmi
|
||||
mgt=ipmi
|
||||
mtm=8247-22L
|
||||
serial=10112CA
|
||||
ip=10.1.2.1
|
||||
ip=10.0.101.1
|
||||
|
||||
#. Define the compute nodes into xCAT: ::
|
||||
|
||||
cat predefined.stanzas | mkdef -z
|
||||
|
||||
#. Set the chain table to run the ``bmcsetup`` script, this will set the BMC IP to static. ::
|
||||
|
||||
@ -106,13 +109,10 @@ The BMC IP address is obtained by the open range dhcp server and the plan in thi
|
||||
|
||||
Set the BMC IP address to a different value for the **predefined** compute node definitions.
|
||||
|
||||
To change the dhcp obtained IP address of 172.30.0.1 to a static IP address of 172.20.2.1, run the following command: ::
|
||||
To change the dhcp obtained IP address of 50.0.100.1 to a static IP address of 50.0.101.1, run the following command: ::
|
||||
|
||||
chdef cn01 bmc=172.20.2.1
|
||||
chdef cn01 bmc=50.0.101.1
|
||||
|
||||
#. Define the compute nodes into xCAT: ::
|
||||
|
||||
cat predefined.stanzas | mkdef -z
|
||||
|
||||
#. Add the compute node IP information to ``/etc/hosts``: ::
|
||||
|
||||
|
@ -12,7 +12,7 @@ The following example outlines the MTMS based hardware discovery for a single IP
|
||||
+------------------------------+------------+
|
||||
| Hostname | cn01 |
|
||||
+------------------------------+------------+
|
||||
| IP address | 10.1.2.1 |
|
||||
| IP address | 10.0.101.1 |
|
||||
+------------------------------+------------+
|
||||
|
||||
The BMC IP address is obtained by the open range dhcp server and the plan is to leave the IP address the same, except we want to change the IP address to be static in the BMC.
|
||||
@ -20,9 +20,9 @@ The BMC IP address is obtained by the open range dhcp server and the plan is to
|
||||
+------------------------------+------------+
|
||||
| BMC Information | Value |
|
||||
+==============================+============+
|
||||
| IP address - dhcp | 172.30.0.1 |
|
||||
| IP address - dhcp | 50.0.100.1 |
|
||||
+------------------------------+------------+
|
||||
| IP address - static | 172.30.0.1 |
|
||||
| IP address - static | 50.0.100.1 |
|
||||
+------------------------------+------------+
|
||||
|
||||
|
||||
@ -30,9 +30,9 @@ The BMC IP address is obtained by the open range dhcp server and the plan is to
|
||||
|
||||
Use the ``bmcdiscover`` command to help discover the nodes over an IP range and easily create a starting file to define the compute nodes into xCAT.
|
||||
|
||||
To discover the compute nodes for the BMCs with an IP address of 172.30.0.1, use the command: ::
|
||||
To discover the compute nodes for the BMCs with an IP address of 50.0.100.1, use the command: ::
|
||||
|
||||
bmcdiscover --range 172.30.0.1 -z > predefined.stanzas
|
||||
bmcdiscover --range 50.0.100.1 -z > predefined.stanzas
|
||||
|
||||
The discovered nodes have the naming convention: node-<*model-type*>-<*serial-number*> ::
|
||||
|
||||
@ -40,7 +40,7 @@ The BMC IP address is obtained by the open range dhcp server and the plan is to
|
||||
node-8247-22l-10112ca:
|
||||
objtype=node
|
||||
groups=all
|
||||
bmc=172.30.0.1
|
||||
bmc=50.0.100.1
|
||||
cons=ipmi
|
||||
mgt=ipmi
|
||||
mtm=8247-22L
|
||||
@ -59,7 +59,7 @@ The BMC IP address is obtained by the open range dhcp server and the plan is to
|
||||
|
||||
#. Add a ``ip`` attribute and give it the compute node IP address: ::
|
||||
|
||||
ip=10.1.2.1
|
||||
ip=10.0.101.1
|
||||
|
||||
#. Repeat for additional nodes in the ``predefined.stanza`` file based on the MTMS mapping.
|
||||
|
||||
@ -70,13 +70,16 @@ The BMC IP address is obtained by the open range dhcp server and the plan is to
|
||||
cn01:
|
||||
objtype=node
|
||||
groups=all
|
||||
bmc=172.30.0.1
|
||||
bmc=50.0.100.1
|
||||
cons=ipmi
|
||||
mgt=ipmi
|
||||
mtm=8247-22L
|
||||
serial=10112CA
|
||||
ip=10.1.2.1
|
||||
ip=10.0.101.1
|
||||
|
||||
#. Define the compute nodes into xCAT: ::
|
||||
|
||||
cat predefined.stanzas | mkdef -z
|
||||
|
||||
#. Set the chain table to run the ``bmcsetup`` script, this will set the BMC IP to static. ::
|
||||
|
||||
@ -86,10 +89,6 @@ The BMC IP address is obtained by the open range dhcp server and the plan is to
|
||||
|
||||
chdef cn01 -p chain="osimage=<osimage_name>"
|
||||
|
||||
#. Define the compute nodes into xCAT: ::
|
||||
|
||||
cat predefined.stanzas | mkdef -z
|
||||
|
||||
#. Add the compute node IP information to ``/etc/hosts``: ::
|
||||
|
||||
makehosts cn01
|
||||
|
@ -15,3 +15,4 @@ Optional means all the subitems in this page are not necessary to finish an OS d
|
||||
install_new_kernel.rst
|
||||
acc_initrd_rootimg_gen_ppc64le.rst
|
||||
trim_diskless_rootimg.rst
|
||||
localdisk.rst
|
||||
|
@ -0,0 +1 @@
|
||||
.. include:: ../../../common/deployment/enable_localdisk.rst
|
@ -0,0 +1,6 @@
|
||||
.. include:: ../../../common/deployment/enable_localdisk.rst
|
||||
|
||||
``Note``:
|
||||
* `localdisk` feature won't syncronize the files/directories defined in `litefile` table from diskless image to local disk at the node boot time. It might casue issue to the application which depends on some of those directories. For example, the ``httpd`` service cannot be started if ``/var/log/`` is defined in `litefile` table. To work around this, you may copy the required contents to local disk and restart service manually at the first time.
|
||||
|
||||
* To keep the contents on local disk after you use ``enablepart=yes`` to do partitioin, make sure to set ``enablepart=no`` in partitioin configuration file after the node is booted.
|
@ -162,91 +162,7 @@ Obtain you new kernel and kernel modules on the MN, for example here we have a n
|
||||
|
||||
uname -a
|
||||
|
||||
Enabling the localdisk Option
|
||||
-----------------------------
|
||||
|
||||
``Note``: You can skip this section if not using the ``localdisk`` option in your litefile table.
|
||||
|
||||
Several things need to be done to enable the 'localdisk' support:
|
||||
|
||||
Define how to partition the local disk
|
||||
``````````````````````````````````````
|
||||
|
||||
When a node is deployed, the local hard disk needs to be partitioned and formatted before it can be used. This section explains how provide a configuration file that tells xCAT to partition a local disk and make it ready to use for the directories listed in the litefile table with the ``localdisk`` option.
|
||||
|
||||
The configuration file needs to be specified in the ``partitionfile`` attribute of the osimage definition. The configuration file includes several parts:
|
||||
|
||||
* Global parameters to control enabling or disabling the function
|
||||
* [disk] part to control the partitioning of the disk
|
||||
* [localspace] part to control which partition will be used to store the localdisk directories listed in the litefile table
|
||||
* [swapspace] part to control the enablement of the swap space for the node.
|
||||
|
||||
An example localdisk configuration file: ::
|
||||
|
||||
enable=yes
|
||||
enablepart=no
|
||||
|
||||
[disk]
|
||||
dev=/dev/sdb
|
||||
clear=yes
|
||||
parts=100M-200M,1G-2G
|
||||
|
||||
[disk]
|
||||
dev=/dev/sda
|
||||
clear=yes
|
||||
parts=10,20,30
|
||||
|
||||
[disk]
|
||||
dev=/dev/sdc
|
||||
clear=yes
|
||||
parts=10,20,30
|
||||
|
||||
[localspace]
|
||||
dev=/dev/sda1
|
||||
fstype=ext3
|
||||
|
||||
[swapspace]
|
||||
dev=/dev/sda2
|
||||
|
||||
The two global parameters ``enable`` and ``enablepart`` can be used to control the enabling/disabling of the functions:
|
||||
|
||||
* enable: The localdisk feature only works when ``enable`` is set to *yes*. If it is set to *no*, the localdisk configuration will not be run.
|
||||
* enablepart: The partition action (refer to the ``[disk]`` section) will be run only when ``enablepart=yes``.
|
||||
|
||||
The ``[disk]`` section is used to configure how to partition a hard disk:
|
||||
|
||||
* dev: The path of the device file.
|
||||
* clear: If set to ``yes`` it will clear all the existing partitions on this disk.
|
||||
* fstype: The file system type for the new created partitions. ``ext3`` is the default value if not set.
|
||||
* parts: A comma separated list of space ranges, one for each partition that will be created on the device. The valid format for each space range is ``<startpoint>-<endpoint>`` or ``<percentage of the disk>``. For example, you could set it to ``100M-10G`` or ``50``. If you set it to ``50``, that means 50% of the disk space will be assigned to that partition.
|
||||
|
||||
The ``[localspace]`` section is used to specify which partition will be used as local storage for the node.
|
||||
|
||||
* dev: The path of the partition.
|
||||
* fstype: The file system type on the partition.
|
||||
|
||||
the ``[swapspace]`` section is used to configure the swap space for the statelite node.
|
||||
|
||||
* dev: The path of the partition file which will be used as the swap space.
|
||||
|
||||
To enable the local disk capability, create the configuration file (for example in ``/install/custom``) and set the path in the partitionfile attribute for the osimage: ::
|
||||
|
||||
chdef -t osimage partitionfile=/install/custom/cfglocaldisk
|
||||
|
||||
Now all nodes that use this osimage (i.e. have their provmethod attribute set to this osimage definition name), will have its local disk configured.
|
||||
|
||||
Configure the files in the litefile table
|
||||
`````````````````````````````````````````
|
||||
|
||||
For the files/directories that you would like xCAT to store on the local disk, add an entry in the litefile table like this: ::
|
||||
|
||||
"ALL","/tmp/","localdisk",,
|
||||
|
||||
``Note``: you do not need to specify the swap space in the litefile table. Just putting it in the partitionfile config file is enough.
|
||||
|
||||
Add an entry in policy table to permit the running of the ``getpartitioin`` command from the node ::
|
||||
|
||||
chtab priority=7.1 policy.commands=getpartition policy.rule=allow
|
||||
.. include:: ../../common/deployment/enable_localdisk.rst
|
||||
|
||||
If Using the RAMdisk-based Image
|
||||
````````````````````````````````
|
||||
|
@ -23,7 +23,7 @@ SYNOPSIS
|
||||
|
||||
\ **bmcdiscover**\ [\ **-v | -**\ **-version**\ ]
|
||||
|
||||
\ **bmcdiscover**\ [\ **-s**\ \ *scan_method*\ ] [\ **-u**\ \ *bmc_user*\ ] [\ **-p**\ \ *bmc_passwd*\ ] [\ **-z**\ ] [\ **-w**\ ] \ **-**\ **-range**\ \ *ip_ranges*\
|
||||
\ **bmcdiscover**\ [\ **-**\ **-sn**\ \ *SN_nodename*\ ] [\ **-s**\ \ *scan_method*\ ] [\ **-u**\ \ *bmc_user*\ ] [\ **-p**\ \ *bmc_passwd*\ ] [\ **-z**\ ] [\ **-w**\ ] \ **-**\ **-range**\ \ *ip_ranges*\
|
||||
|
||||
\ **bmcdiscover**\ \ **-u**\ \ *bmc_user*\ \ **-p**\ \ *bmc_passwd*\ \ **-i**\ \ *bmc_ip*\ \ **-**\ **-check**\
|
||||
|
||||
@ -56,6 +56,12 @@ OPTIONS
|
||||
|
||||
|
||||
|
||||
\ **-**\ **-sn**\
|
||||
|
||||
Specify one or more service nodes on which bmcdiscover will run. In hierarchical cluster, the MN may not be able to access the BMC of CN directly, but SN can. With this option, bmcdiscover will be dispatched to the specified SNs. Then, the nodename of the service node that 'bmcdiscover' is running on will be set to the 'servicenode' attribute of the discovered BMC node.
|
||||
|
||||
|
||||
|
||||
\ **-s**\
|
||||
|
||||
Scan method (The only supported scan method at this time is \ **nmap**\ )
|
||||
@ -142,7 +148,7 @@ EXAMPLES
|
||||
|
||||
Note: Input for IP range can be in the form: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254.
|
||||
|
||||
2. To get all BMSs in IP range "10.4.22-23.100-254", displayed in xCAT stanza format:
|
||||
2. To get all BMCs in IP range "10.4.22-23.100-254", displayed in xCAT stanza format:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
@ -150,7 +156,30 @@ Note: Input for IP range can be in the form: scanme.nmap.org, microsoft.com/24,
|
||||
bmcdiscover -s nmap --range "10.4.22-23.100-254" -z
|
||||
|
||||
|
||||
3. Discover the BMCs and write the discovered-node definitions into the xCAT database and write out the stanza foramt to the console:
|
||||
3. To discover BMCs through sn01:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
bmcdiscover --sn sn01 -s nmap --range "10.4.22-23.100-254" -z
|
||||
|
||||
|
||||
Output is similar to:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
node-70e28414291b:
|
||||
objtype=node
|
||||
groups=all
|
||||
bmc=10.4.22.101
|
||||
cons=openbmc
|
||||
mgt=openbmc
|
||||
servicenode=sn01
|
||||
conserver=sn01
|
||||
|
||||
|
||||
4. Discover the BMCs and write the discovered-node definitions into the xCAT database and write out the stanza foramt to the console:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
@ -158,7 +187,7 @@ Note: Input for IP range can be in the form: scanme.nmap.org, microsoft.com/24,
|
||||
bmcdiscover -s nmap --range "10.4.22-23.100-254" -w -z
|
||||
|
||||
|
||||
4. To check if the username or password is correct against the BMC:
|
||||
5. To check if the username or password is correct against the BMC:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
@ -166,7 +195,7 @@ Note: Input for IP range can be in the form: scanme.nmap.org, microsoft.com/24,
|
||||
bmcdiscover -i 10.4.23.254 -u USERID -p PASSW0RD --check
|
||||
|
||||
|
||||
5. Get BMC IP Address source, DHCP Address or static Address
|
||||
6. Get BMC IP Address source, DHCP Address or static Address
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
@ -19,7 +19,7 @@ SYNOPSIS
|
||||
********
|
||||
|
||||
|
||||
\ **nodediscoverls**\ [\ **-t seq | profile | switch | blade | manual | undef | all**\ ] [\ **-l**\ ]
|
||||
\ **nodediscoverls**\ [\ **-t seq | profile | switch | blade | manual | mtms | undef | all**\ ] [\ **-l**\ ]
|
||||
|
||||
\ **nodediscoverls**\ [\ **-u**\ \ *uuid*\ ] [\ **-l**\ ]
|
||||
|
||||
@ -47,7 +47,7 @@ OPTIONS
|
||||
|
||||
|
||||
|
||||
\ **-t seq|profile|switch|blade|manual|undef|all**\
|
||||
\ **-t seq|profile|switch|blade|manual|mtms|undef|all**\
|
||||
|
||||
Display the nodes that have been discovered by the specified discovery method:
|
||||
|
||||
@ -72,6 +72,10 @@ OPTIONS
|
||||
|
||||
|
||||
|
||||
\* \ **mtms**\ - MTMS discovery (used when node mtm and serial fields are filled in).
|
||||
|
||||
|
||||
|
||||
\* \ **undef**\ - Display the nodes that were in the discovery pool, but for which xCAT has not yet received a discovery request.
|
||||
|
||||
|
||||
|
@ -50,14 +50,20 @@ OpenPOWER BMC specific (using IPMI):
|
||||
====================================
|
||||
|
||||
|
||||
\ **rflash**\ \ *noderange*\ [\ *hpm_file_path*\ | \ **-d=**\ \ *data_directory*\ ] [\ **-c | -**\ **-check**\ ] [\ **-**\ **-retry=**\ \ *count*\ ] [\ **-V**\ ]
|
||||
\ **rflash**\ \ *noderange*\ [\ *hpm_file_path*\ | \ **-d**\ \ *data_directory*\ ] [\ **-c | -**\ **-check**\ ] [\ **-**\ **-retry=**\ \ *count*\ ] [\ **-V**\ ]
|
||||
|
||||
\ **rflash**\ \ *noderange*\ \ **-**\ **-recover**\ \ *bmc_file_path*\
|
||||
|
||||
|
||||
OpenPOWER OpenBMC specific :
|
||||
============================
|
||||
|
||||
|
||||
\ **rflash**\ \ *noderange*\ [\ *tar_file_path*\ | \ *image_id*\ ] [\ **-c | -**\ **-check**\ ] [\ **-a | -**\ **-activate**\ ] [\ **-l | -**\ **-list**\ ] [\ **-u | -**\ **-upload**\ ] [\ **-d | -**\ **-delete**\ ]
|
||||
\ **rflash**\ \ *noderange*\ {[\ **-c | -**\ **-check**\ ] | [\ **-l | -**\ **-list**\ ]}
|
||||
|
||||
\ **rflash**\ \ *noderange*\ \ *tar_file_path*\ {[\ **-c | -**\ **-check**\ ] | [\ **-a | -**\ **-activate**\ ] | [\ **-u | -**\ **-upload**\ ]}
|
||||
|
||||
\ **rflash**\ \ *noderange*\ \ *image_id*\ {[\ **-a | -**\ **-activate**\ ] | [\ **-d | -**\ **-delete**\ ]}
|
||||
|
||||
|
||||
|
||||
@ -168,11 +174,11 @@ The command will update firmware for OpenPOWER OpenBMC when given an OpenPOWER n
|
||||
|
||||
\ **-d**\ \ *data_directory*\
|
||||
|
||||
PPC (without HMC, using Direct FSP Management) specific:
|
||||
|
||||
Specifies the directory where the raw data from rpm packages for each CEC/Frame are located. The default directory is /tmp. The option is only used in Direct FSP/BPA Management.
|
||||
|
||||
|
||||
|
||||
\ **-d=**\ \ *data_directory*\
|
||||
OpenPOWER BMC specific (using IPMI):
|
||||
|
||||
Used for IBM Power S822LC for Big Data systems only. Specifies the directory where the \ **pUpdate**\ utility and at least one of BMC or PNOR update files are located. The utility and update files can be downloaded from FixCentral.
|
||||
|
||||
@ -192,8 +198,14 @@ The command will update firmware for OpenPOWER OpenBMC when given an OpenPOWER n
|
||||
|
||||
\ **-**\ **-recover**\
|
||||
|
||||
PPC (with HMC) and PPC (without HMC, using Direct FSP Management) specific:
|
||||
|
||||
Used to recover the flash image in the permanent side of the chip to the temporary side for both managed systems and power subsystems.
|
||||
|
||||
OpenPOWER BMC specific (using IPMI):
|
||||
|
||||
Used for IBM Power S822LC for Big Data systems only. Used to recover the BMC with a BMC image downloaded from FixCentral.
|
||||
|
||||
|
||||
|
||||
\ **-**\ **-retry=**\ \ *count*\
|
||||
@ -204,7 +216,7 @@ The command will update firmware for OpenPOWER OpenBMC when given an OpenPOWER n
|
||||
|
||||
\ **-a|-**\ **-activate**\
|
||||
|
||||
Activate update image. Image id must be specified.
|
||||
Activate update image. Image id or update file must be specified.
|
||||
|
||||
|
||||
|
||||
@ -318,7 +330,17 @@ The command will update firmware for OpenPOWER OpenBMC when given an OpenPOWER n
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
rflash briggs01 -d=/root/supermicro/OP825
|
||||
rflash briggs01 -d /root/supermicro/OP825
|
||||
|
||||
|
||||
|
||||
|
||||
7. To update the firmware on the OpenBMC machine, specify the firmare update file to upload and activate:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
rflash p9euh02 -a /tmp/witherspoon.pnor.squashfs.tar
|
||||
|
||||
|
||||
|
||||
|
@ -11,7 +11,7 @@ SYNOPSIS
|
||||
********
|
||||
|
||||
|
||||
\ **rsetboot**\ \ *noderange*\ {\ **hd | net | cd | default | stat**\ } [\ **-u**\ ] [\ **-p**\ ]
|
||||
\ **rsetboot**\ \ *noderange*\ [\ **hd | net | cd | default | stat**\ ] [\ **-u**\ ] [\ **-p**\ ]
|
||||
|
||||
\ **rsetboot**\ [\ **-h | -**\ **-help | -v | -**\ **-version**\ ]
|
||||
|
||||
@ -21,7 +21,7 @@ DESCRIPTION
|
||||
***********
|
||||
|
||||
|
||||
\ **rsetboot**\ sets the boot media and boot mode that should be used on the next boot of the specified nodes. After the nodes are booted with the specified device and boot mode (e.g. via rpower(1)|rpower.1), the nodes will return to using the default boot device specified in the BIOS. Currently this command is only supported for IPMI nodes.
|
||||
\ **rsetboot**\ sets the boot media and boot mode that should be used on the next boot of the specified nodes. After the nodes are booted with the specified device and boot mode (e.g. via rpower(1)|rpower.1), the nodes will return to using the default boot device specified in the BIOS.
|
||||
|
||||
|
||||
*******
|
||||
@ -101,6 +101,14 @@ EXAMPLES
|
||||
rsetboot node[14-56],node[70-203] stat
|
||||
|
||||
|
||||
Or:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
rsetboot node[14-56],node[70-203]
|
||||
|
||||
|
||||
|
||||
|
||||
3.
|
||||
|
@ -47,7 +47,7 @@ OpenBMC specific:
|
||||
=================
|
||||
|
||||
|
||||
\ **rspconfig**\ \ *noderange*\ {\ **ip | netmask | gateway | vlan | sshcfg**\ }
|
||||
\ **rspconfig**\ \ *noderange*\ {\ **ip | netmask | gateway | hostname | vlan | sshcfg**\ }
|
||||
|
||||
|
||||
MPA specific:
|
||||
@ -394,6 +394,12 @@ OPTIONS
|
||||
|
||||
|
||||
|
||||
\ **hostname**\
|
||||
|
||||
Get or set hostname on the service processor.
|
||||
|
||||
|
||||
|
||||
\ **vlan**\
|
||||
|
||||
Get or set vlan ID. For get vlan ID, if vlan is not enabled, 'BMC VLAN disabled' will be outputed. For set vlan ID, the valid value are [1-4096].
|
||||
|
@ -15,7 +15,7 @@ SYNOPSIS
|
||||
|
||||
\ **switchdiscover [-v| -**\ **-version]**\
|
||||
|
||||
\ **switchdiscover**\ [\ *noderange*\ | \ **-**\ **-range**\ \ *ip_ranges*\ ] \ **[-V] [-w][-r|-x|-z][-s**\ \ *scan_methods*\ \ **-**\ **-setup**\ ]
|
||||
\ **switchdiscover**\ [\ *noderange*\ | \ **-**\ **-range**\ \ *ip_ranges*\ ] \ **[-V] [-w][-r|-x|-z][-s**\ \ *scan_methods*\ ] [\ **-**\ **-setup**\ ] [\ **-c**\ \ *community*\ ]
|
||||
|
||||
|
||||
***********
|
||||
@ -31,7 +31,7 @@ To view all the switches defined in the xCAT database use \ **lsdef -w "nodetype
|
||||
|
||||
For lldp method, make sure that lldpd package is installed and lldpd is running on the xCAT management node. lldpd comes from xcat-dep package or you can get it from http://vincentbernat.github.io/lldpd/installation.html.
|
||||
|
||||
For snmp method, make sure that snmpwalk command is installed and snmp is enabled for switches. To install snmpwalk, "yum install net-snmp-utils" for redhat and sles, "apt-get install snmp" for Ubuntu.
|
||||
For snmp method, make sure that snmpwalk command is installed and snmp is enabled for switches. To install snmpwalk, "yum install net-snmp-utils" for redhat and sles, "apt-get install snmp" for Ubuntu. The switchdiscover command only check the switches with default community string, if user already configured switch with other commmunity string, need to pass in with \ **-c**\ option for switchdiscover command to be able to discover.
|
||||
|
||||
|
||||
*******
|
||||
@ -118,6 +118,12 @@ OPTIONS
|
||||
|
||||
|
||||
|
||||
\ **-c**\
|
||||
|
||||
User defined community string for snmp scan.
|
||||
|
||||
|
||||
|
||||
|
||||
************
|
||||
RETURN VALUE
|
||||
|
@ -129,7 +129,7 @@ nics Attributes:
|
||||
\ **nicsadapter**\
|
||||
|
||||
Comma-separated list of extra parameters that will be used for each NIC configuration.
|
||||
<nic1>!<param1=value1 param2=value2>|<param3=value3>,<nic2>!<param4=value4 param5=value5>|<param6=value6>, for example, eth0!MTU=1500|MTU=1460,ib0!MTU=65520 CONNECTED_MODE=yes.
|
||||
<nic1>!<param1=value1 param2=value2>,<nic2>!<param4=value4 param5=value5>, for example, enP3p3s0f1!mac=98:be:94:59:fa:cd linkstate=DOWN,enP3p3s0f2!mac=98:be:94:59:fa:ce candidatename=enP3p3s0f2/enx98be9459face
|
||||
|
||||
|
||||
|
||||
|
@ -390,6 +390,18 @@ site Attributes:
|
||||
hierarchicalattrs: Table attributes(e.g. postscripts, postbootscripts) that will be
|
||||
included hierarchically. Attribute values for all the node's groups
|
||||
will be applied to the node in the groups' order except the repeat one.
|
||||
dbtracelevel: The trace level for the database access log. To activate this setting, please.
|
||||
restart xcatd or send HUP signal to the 'xcatd: DB Access' process, Like: .
|
||||
ps -ef | grep 'xcatd: DB Access' | grep -v grep | awk '{print $2}' | xargs kill -HUP
|
||||
Currrent support values:
|
||||
0: disable the trace log for db
|
||||
1: trace the calls of database subroutines
|
||||
2: Besides the log from level 1, trace the event to build the cache for the table
|
||||
3: Besides the log from level 2, trace the event with cache hit
|
||||
4: Besides the log from level 3, trace the SQL statement for the db access
|
||||
With this configuration, xcat will send the log to syslog very frequently, some of the
|
||||
log may be lost if imjournal is enabled by rsyslog.
|
||||
Please see https://github.com/xcat2/xcat-core/issues/3910 for the detail.
|
||||
|
||||
-----------------------
|
||||
VIRTUALIZATION ATTRIBUTES
|
||||
|
@ -166,6 +166,46 @@ As of xCAT 2.8.1, you can use a modified version of the regular expression suppo
|
||||
http://xcat-docs.readthedocs.org/en/latest/guides/admin-guides/basic_concepts/xcat_db/regexp_db.html#easy-regular-expressions
|
||||
|
||||
|
||||
Regular Expression Helper Functions
|
||||
===================================
|
||||
|
||||
|
||||
xCAT provides several functions that can simplify regular expressions.
|
||||
|
||||
|
||||
\ **a2idx**\
|
||||
|
||||
ASCII Character to Index
|
||||
|
||||
|
||||
|
||||
\ **a2zidx**\
|
||||
|
||||
ASCII Character to 0-Index
|
||||
|
||||
|
||||
|
||||
\ **dim2idx**\
|
||||
|
||||
Dimensions to Index
|
||||
|
||||
|
||||
|
||||
\ **skip**\
|
||||
|
||||
Skip indices
|
||||
|
||||
|
||||
|
||||
\ **ipadd**\
|
||||
|
||||
Add to an IP address
|
||||
|
||||
|
||||
|
||||
http://xcat-docs.readthedocs.org/en/latest/guides/admin-guides/basic_concepts/xcat_db/regexp_db.html#regular-expression-helper-functions
|
||||
|
||||
|
||||
|
||||
******************
|
||||
OBJECT DEFINITIONS
|
||||
|
@ -41,7 +41,7 @@ group Attributes:
|
||||
|
||||
\ **addkcmdline**\ (bootparams.addkcmdline)
|
||||
|
||||
User specified one or more parameters to be passed to the kernel. For the kernel options need to be persistent after installation, specify them with prefix "R::"
|
||||
User specified kernel options for os provision process(no prefix) or the provisioned os(with prefix "R::"). The options should be delimited with spaces(" ")
|
||||
|
||||
|
||||
|
||||
@ -669,7 +669,7 @@ group Attributes:
|
||||
\ **nicsadapter**\ (nics.nicsadapter)
|
||||
|
||||
Comma-separated list of extra parameters that will be used for each NIC configuration.
|
||||
<nic1>!<param1=value1 param2=value2>|<param3=value3>,<nic2>!<param4=value4 param5=value5>|<param6=value6>, for example, eth0!MTU=1500|MTU=1460,ib0!MTU=65520 CONNECTED_MODE=yes.
|
||||
<nic1>!<param1=value1 param2=value2>,<nic2>!<param4=value4 param5=value5>, for example, enP3p3s0f1!mac=98:be:94:59:fa:cd linkstate=DOWN,enP3p3s0f2!mac=98:be:94:59:fa:ce candidatename=enP3p3s0f2/enx98be9459face
|
||||
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ node Attributes:
|
||||
|
||||
\ **addkcmdline**\ (bootparams.addkcmdline)
|
||||
|
||||
User specified one or more parameters to be passed to the kernel. For the kernel options need to be persistent after installation, specify them with prefix "R::"
|
||||
User specified kernel options for os provision process(no prefix) or the provisioned os(with prefix "R::"). The options should be delimited with spaces(" ")
|
||||
|
||||
|
||||
|
||||
@ -669,7 +669,7 @@ node Attributes:
|
||||
\ **nicsadapter**\ (nics.nicsadapter)
|
||||
|
||||
Comma-separated list of extra parameters that will be used for each NIC configuration.
|
||||
<nic1>!<param1=value1 param2=value2>|<param3=value3>,<nic2>!<param4=value4 param5=value5>|<param6=value6>, for example, eth0!MTU=1500|MTU=1460,ib0!MTU=65520 CONNECTED_MODE=yes.
|
||||
<nic1>!<param1=value1 param2=value2>,<nic2>!<param4=value4 param5=value5>, for example, enP3p3s0f1!mac=98:be:94:59:fa:cd linkstate=DOWN,enP3p3s0f2!mac=98:be:94:59:fa:ce candidatename=enP3p3s0f2/enx98be9459face
|
||||
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ osimage Attributes:
|
||||
|
||||
\ **addkcmdline**\ (linuximage.addkcmdline)
|
||||
|
||||
User specified arguments to be passed to the kernel. The user arguments are appended to xCAT.s default kernel arguments. For the kernel options need to be persistent after installation, specify them with prefix "R::". This attribute is ignored if linuximage.boottarget is set.
|
||||
User specified kernel options for os provision process(no prefix) or the provisioned os(with prefix "R::"). The options should be delimited with spaces(" "). This attribute is ignored if linuximage.boottarget is set.
|
||||
|
||||
|
||||
|
||||
|
@ -14,6 +14,84 @@ xCAT 2.13.x
|
||||
|xCAT |New OS |New |New Feature |
|
||||
|Version | |Hardware | |
|
||||
+=================================+===============+=============+==================================+
|
||||
|| xCAT 2.13.7 | | |- OpenBMC support: |
|
||||
|| 2017/9/22 | | | |
|
||||
|| | | | rflash for OpenBMC and PNOR |
|
||||
| `2.13.7 Release Notes <https:// | | | |
|
||||
| github.com/xcat2/xcat-core/wiki | | | reventlog to get/clear event log|
|
||||
| /XCAT_2.13.7_Release_Notes>`_ | | | |
|
||||
| | | |- xcatprobe clusterstatus enhance |
|
||||
| | | | |
|
||||
| | | |- PDU support: discover, config |
|
||||
| | | | |
|
||||
| | | |- SRIOV support for VMs |
|
||||
+---------------------------------+---------------+-------------+----------------------------------+
|
||||
|| xCAT 2.13.6 |- RHEL 7.4 |- Boston |- OpenBMC support |
|
||||
|| 2017/8/10 | | server | |
|
||||
|| | | | rsetboot net/hd/def |
|
||||
| `2.13.6 Release Notes <https:// | | | |
|
||||
| github.com/xcat2/xcat-core/wiki | | | rflash list/upload/activate |
|
||||
| /XCAT_2.13.6_Release_Notes>`_ | | | /delete/check |
|
||||
| | | | |
|
||||
| | | | rspconfig retrieve OpenBMC ip/ |
|
||||
| | | | netmask/gateway information |
|
||||
| | | |- nodeset performance enhancement |
|
||||
| | | | (Phase 3) |
|
||||
| | | | |
|
||||
| | | | Dispatch request to the |
|
||||
| | | | specified service nodes with |
|
||||
| | | | 'disjointdhcps' |
|
||||
| | | | |
|
||||
| | | | Enhance the output of nodeset |
|
||||
| | | | in hierarchical cluster |
|
||||
| | | | |
|
||||
| | | |- network configuration interface:|
|
||||
| | | | |
|
||||
| | | | confignetwork is the only |
|
||||
| | | | interface to configure network |
|
||||
| | | | on SN/CN |
|
||||
| | | | |
|
||||
| | | |- For hardware discovery |
|
||||
| | | | |
|
||||
| | | | enhance bmcdiscover to use BMC |
|
||||
| | | | MAC address to identify BMC with|
|
||||
| | | | its host |
|
||||
| | | | |
|
||||
| | | | enhance "xcatprobe discovery" |
|
||||
| | | | tool to do configuration check |
|
||||
| | | | before starting hardware |
|
||||
| | | | discovery |
|
||||
| | | | |
|
||||
| | | |- [xcat-deps] xcat-genesis-base |
|
||||
| | | | package based on Fedora 26 ppc64|
|
||||
+---------------------------------+---------------+-------------+----------------------------------+
|
||||
|| xCAT 2.13.5 | | |- OpenBMC support |
|
||||
|| 2017/6/30 | | | |
|
||||
|| | | | rinv |
|
||||
| `2.13.5 Release Notes <https:// | | | rinstall |
|
||||
| github.com/xcat2/xcat-core/wiki | | | bmcdiscover |
|
||||
| /XCAT_2.13.5_Release_Notes>`_ | | |- Enhancements to self testing |
|
||||
| | | | tool xcat-test |
|
||||
| | | |- Service node pool support for |
|
||||
| | | | rhels7 ppc64le diskless |
|
||||
| | | |- Mellanox cumulus switch ZTP |
|
||||
| | | | based discovery and |
|
||||
| | | | auto-configuration |
|
||||
| | | |- Performance enhancements |
|
||||
| | | | |
|
||||
| | | | makedhcp, makedns |
|
||||
| | | | nodeset |
|
||||
| | | |- [xcat-deps] ipmitool-xcat |
|
||||
| | | | package updated to version |
|
||||
| | | | 1.8.18 for |
|
||||
| | | | |
|
||||
| | | | RHEL7.x |
|
||||
| | | | SLES12.x |
|
||||
| | | | Ubuntu14.04.x |
|
||||
| | | |- [xcat-deps] conserver-xcat |
|
||||
| | | | package updated to version 8.2.1|
|
||||
| | | | |
|
||||
+---------------------------------+---------------+-------------+----------------------------------+
|
||||
|| xCAT 2.13.4 |- RHV 4.1 | |- OpenBMC support(experimental): |
|
||||
|| 2017/5/19 | | | |
|
||||
|| | | | rinv |
|
||||
|
2
makerpm
2
makerpm
@ -145,6 +145,8 @@ function makexcat {
|
||||
cp xcat.conf $RPMROOT/SOURCES
|
||||
cp xcat.conf.apach24 $RPMROOT/SOURCES
|
||||
cp xCATSN $RPMROOT/SOURCES
|
||||
cp -a ../xCAT/etc/rsyslog.d $RPMROOT/
|
||||
cp -a ../xCAT/etc/logrotate.d $RPMROOT/
|
||||
cd - >/dev/null
|
||||
elif [ "$RPMNAME" = "xCAT-buildkit" ]; then
|
||||
ARCH="noarch"
|
||||
|
@ -271,6 +271,36 @@ As of xCAT 2.8.1, you can use a modified version of the regular expression suppo
|
||||
|
||||
http://xcat-docs.readthedocs.org/en/latest/guides/admin-guides/basic_concepts/xcat_db/regexp_db.html#easy-regular-expressions
|
||||
|
||||
=head2 Regular Expression Helper Functions
|
||||
|
||||
xCAT provides several functions that can simplify regular expressions.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<a2idx>
|
||||
|
||||
ASCII Character to Index
|
||||
|
||||
=item B<a2zidx>
|
||||
|
||||
ASCII Character to 0-Index
|
||||
|
||||
=item B<dim2idx>
|
||||
|
||||
Dimensions to Index
|
||||
|
||||
=item B<skip>
|
||||
|
||||
Skip indices
|
||||
|
||||
=item B<ipadd>
|
||||
|
||||
Add to an IP address
|
||||
|
||||
=back
|
||||
|
||||
http://xcat-docs.readthedocs.org/en/latest/guides/admin-guides/basic_concepts/xcat_db/regexp_db.html#regular-expression-helper-functions
|
||||
|
||||
=head1 OBJECT DEFINITIONS
|
||||
|
||||
Because it can get confusing what attributes need to go in what tables, the xCAT database can also
|
||||
|
@ -184,7 +184,7 @@ sub updateUserInfo {
|
||||
|
||||
# update the merge file
|
||||
my $mergefile = $cfmdir . "/" . $file . ".merge";
|
||||
my @diff = xCAT::CFMUtils->arrayops("D", \@newrecords, \@oldrecords);
|
||||
my @diff = xCAT::CFMUtils->arrayops("D", \@newrecords, \@oldrecords, 1);
|
||||
|
||||
# output the diff to merge files
|
||||
my $fp;
|
||||
@ -865,6 +865,7 @@ sub trim {
|
||||
$flag - "U"/"I"/"D"
|
||||
\@array1 - reference to an arrary
|
||||
\@array2 - reference to an arrary
|
||||
$odered - flag to keep pervious order
|
||||
Returns:
|
||||
@union/@intersection/@difference
|
||||
Globals:
|
||||
@ -878,7 +879,7 @@ sub trim {
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
sub arrayops {
|
||||
my ($class, $ops, $array1, $array2) = @_;
|
||||
my ($class, $ops, $array1, $array2, $ordered) = @_;
|
||||
|
||||
my @union = ();
|
||||
my @intersection = ();
|
||||
@ -886,21 +887,23 @@ sub arrayops {
|
||||
my %count = ();
|
||||
foreach my $element (@$array1, @$array2)
|
||||
{
|
||||
$count{$element}++
|
||||
$count{$element}++;
|
||||
push @union, $element unless ( $count{$element} > 1 );
|
||||
}
|
||||
|
||||
foreach my $element (keys %count) {
|
||||
push @union, $element;
|
||||
unless( defined($ordered) and $ordered ) {
|
||||
@union = keys %count;
|
||||
}
|
||||
|
||||
foreach my $element (@union) {
|
||||
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
|
||||
}
|
||||
|
||||
if ($ops eq "U") { return @union; }
|
||||
|
||||
if ($ops eq "I") { return @intersection; }
|
||||
|
||||
if ($ops eq "D") { return @difference; }
|
||||
|
||||
#return (\@union, \@intersection, \@difference);
|
||||
}
|
||||
|
||||
|
||||
|
@ -225,7 +225,7 @@ sub rvlan {
|
||||
my $switchestab = xCAT::Table->new('switches', -create => 0);
|
||||
my @switchesents;
|
||||
if ($switchestab) {
|
||||
foreach (values %{ $switchestab->getNodesAttribs($switches, [qw(switch snmpversion username password privacy auth)]) }) {
|
||||
foreach (values %{ $switchestab->getNodesAttribs($switches, [qw(switch snmpversion username password privacy auth switchtype)]) }) {
|
||||
push @switchesents, @$_;
|
||||
}
|
||||
}
|
||||
@ -309,7 +309,7 @@ sub dump_mac_info {
|
||||
}
|
||||
}
|
||||
my $switchestab = xCAT::Table->new('switches', -create => 0);
|
||||
my @switchesents = $switchestab->getAllNodeAttribs([qw(switch snmpversion username password privacy auth)]);
|
||||
my @switchesents = $switchestab->getAllNodeAttribs([qw(switch snmpversion username password privacy auth switchtype)]);
|
||||
$self->fill_switchparms(community => $community, switchesents => \@switchesents);
|
||||
my $switchtab = xCAT::Table->new('switch', -create => 0);
|
||||
my @entries = ();
|
||||
@ -337,7 +337,12 @@ sub dump_mac_info {
|
||||
if ($self->{show_verbose_info}) {
|
||||
xCAT::MsgUtils->message("I", { data => ["<INFO>$switch: Attempting to refresh switch information..."] }, $self->{callback});
|
||||
}
|
||||
my $probestart = time;
|
||||
$self->refresh_switch(undef, $community, $switch);
|
||||
my $probestop = time;
|
||||
my $probeduration = $probestop - $probestart;
|
||||
xCAT::MsgUtils->message("S", "xcatprobe refresh_switch $switch ElapsedTime:$probeduration sec");
|
||||
|
||||
if ($self->{show_verbose_info}) {
|
||||
xCAT::MsgUtils->message("I", { data => ["<INFO>$switch: Finished refreshing switch information."] }, $self->{callback});
|
||||
}
|
||||
@ -403,7 +408,13 @@ sub find_mac {
|
||||
#If requesting a cache only check or the cache is a mere 20 seconds old
|
||||
#don't bother querying switches
|
||||
if ($cachedonly or ($self->{timestamp} > (time() - 20))) { return undef; }
|
||||
|
||||
my $runstart = time;
|
||||
$self->refresh_table($discover_switch); #not cached or stale cache, refresh
|
||||
my $runstop = time;
|
||||
my $diffduration = $runstop - $runstart;
|
||||
xCAT::MsgUtils->message("S", "refresh_table ElapsedTime:$diffduration sec");
|
||||
|
||||
if ($self->{mactable}->{ lc($mac) }) {
|
||||
return $self->{mactable}->{ lc($mac) };
|
||||
}
|
||||
@ -419,6 +430,7 @@ sub fill_switchparms {
|
||||
foreach (@switchentries) {
|
||||
my $curswitch = $_->{switch};
|
||||
$self->{switchparmhash}->{$curswitch} = $_;
|
||||
$self->{switchparmhash}->{$curswitch}->{switchtype}=$_->{switchtype};
|
||||
if ($_->{snmpversion}) {
|
||||
if ($_->{snmpversion} =~ /3/) { #clean up to accept things like v3 or ver3 or 3, whatever.
|
||||
$self->{switchparmhash}->{$curswitch}->{snmpversion} = 3;
|
||||
@ -444,7 +456,7 @@ sub refresh_table {
|
||||
$self->{mactable} = {};
|
||||
$self->{switchtab} = xCAT::Table->new('switch', -create => 1);
|
||||
$self->{switchestab} = xCAT::Table->new('switches', -create => 1);
|
||||
my @switchentries = $self->{switchestab}->getAllNodeAttribs([qw(switch snmpversion username password privacy auth)]);
|
||||
my @switchentries = $self->{switchestab}->getAllNodeAttribs([qw(switch snmpversion username password privacy auth switchtype)]);
|
||||
my $community = "public";
|
||||
|
||||
#$self->{sitetab} = xCAT::Table->new('site');
|
||||
@ -477,6 +489,9 @@ sub refresh_table {
|
||||
unless (defined $_->{password}) { #if no password set, inherit the community
|
||||
$self->{switchparmhash}->{$curswitch}->{password} = $community;
|
||||
}
|
||||
if (defined $_->{switchtype}){
|
||||
$self->{switchparmhash}->{$curswitch}->{switchtype} =$_->{switchtype};
|
||||
}
|
||||
}
|
||||
my %checked_pairs;
|
||||
my @entries = $self->{switchtab}->getAllNodeAttribs([ 'node', 'port', 'switch' ]);
|
||||
@ -497,7 +512,7 @@ sub refresh_table {
|
||||
my $ntype = $typehash->{$entry->{node}}->[0]->{nodetype};
|
||||
if ( (($discover_switch) and ( $ntype ne "switch"))
|
||||
or ( !($discover_switch) and ( $ntype eq "switch")) ){
|
||||
xCAT::MsgUtils->message("S", "refresh_table: skip $entry->{node} and $entry->{switch}");
|
||||
xCAT::MsgUtils->message("S", "refresh_table: skip $entry->{node} and $entry->{switch}, $discover_switch , $ntype\n");
|
||||
next;
|
||||
}
|
||||
if (defined($entry->{switch}) and $entry->{switch} ne "" and defined($entry->{port}) and $entry->{port} ne "") {
|
||||
@ -528,15 +543,28 @@ sub refresh_table {
|
||||
pipe my $child, my $parent;
|
||||
$child->autoflush(1);
|
||||
$parent->autoflush(1);
|
||||
|
||||
$children++;
|
||||
my $cpid = xCAT::Utils->xfork;
|
||||
unless (defined $cpid) { die "Cannot fork" }
|
||||
unless (defined $cpid) {
|
||||
$children--;
|
||||
close($child);
|
||||
close($parent);
|
||||
xCAT::MsgUtils->message("S", "refresh_table: failed to fork refresh_switch process for $entry->{switch},skip...");
|
||||
next;
|
||||
}
|
||||
|
||||
if ($cpid == 0) {
|
||||
$SIG{CHLD} = 'DEFAULT';
|
||||
close($child);
|
||||
my $runstart = time;
|
||||
$self->refresh_switch($parent, $community, $entry->{switch});
|
||||
my $runstop = time;
|
||||
my $diffduration = $runstop - $runstart;
|
||||
xCAT::MsgUtils->message("S", "refresh_switch $entry->{switch} ElapsedTime:$diffduration sec");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close($parent);
|
||||
$inputs->add($child);
|
||||
}
|
||||
@ -615,6 +643,9 @@ sub walkoid {
|
||||
return $retmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sub getsnmpsession {
|
||||
|
||||
#gets an snmp v3 session appropriate for a switch using the switches table for guidance on the hows
|
||||
@ -688,7 +719,54 @@ sub refresh_switch {
|
||||
my $community = shift;
|
||||
my $switch = shift;
|
||||
|
||||
#if ($error) { die $error; }
|
||||
unless($self->{collect_mac_info})
|
||||
{
|
||||
if($self->{switchparmhash}->{$switch}->{switchtype} eq 'onie'){
|
||||
#for cumulus switch, the MAC table can be retrieved with ssh
|
||||
#which is much faster than snmp
|
||||
my $mymac;
|
||||
my $myport;
|
||||
|
||||
my @res=xCAT::Utils->runcmd("ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no $switch 'bridge fdb show|grep -i -v permanent|tr A-Z a-z 2>/dev/null' 2>/dev/null",-1);
|
||||
if ($::RUNCMD_RC) {
|
||||
xCAT::MsgUtils->message("S", "Failed to get mac table with ssh to $switch, fall back to snmp! To obtain mac table with ssh, please make sure the passwordless root ssh to $switch is available");
|
||||
}else{
|
||||
foreach (@res){
|
||||
if($_ =~ m/^([0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}) dev swp([0-9]+) .*/){
|
||||
$mymac=$1;
|
||||
$myport=$2;
|
||||
$myport=sprintf("%d",$myport);
|
||||
|
||||
#try all the possible port number formats
|
||||
#e.g, "5","swp5","05","swp05"
|
||||
unless(exists $self->{switches}->{$switch}->{$myport}){
|
||||
if(exists $self->{switches}->{$switch}->{"swp".$myport}){
|
||||
$myport="swp".$myport;
|
||||
}else{
|
||||
$myport=sprintf("%02d",$myport);
|
||||
unless(exists $self->{switches}->{$switch}->{$myport}){
|
||||
if(exists $self->{switches}->{$switch}->{"swp".$myport}){
|
||||
$myport="swp".$myport;
|
||||
}else{
|
||||
$myport="";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($myport){
|
||||
if($output){
|
||||
printf $output "$mymac|%s\n", $self->{switches}->{$switch}->{$myport};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $session = $self->getsnmpsession('community' => $community, 'switch' => $switch);
|
||||
unless ($session) {
|
||||
xCAT::MsgUtils->message("S", "Failed to communicate with $switch");
|
||||
@ -734,6 +812,9 @@ sub refresh_switch {
|
||||
xCAT::MsgUtils->message("I", "MTU information is not availabe for this switch $switch");
|
||||
}
|
||||
|
||||
# get port state
|
||||
my $mactostate = walkoid($session, '.1.3.6.1.2.1.17.7.1.2.2.1.3', silentfail => 1, verbose => $self->{show_verbose_info}, switch => $switch, callback => $self->{callback});
|
||||
|
||||
#Above is valid without community string indexing, on cisco, we need it on the next one and onward
|
||||
my $iftovlanmap = walkoid($session, '.1.3.6.1.4.1.9.9.68.1.2.2.1.2', silentfail => 1, verbose => $self->{show_verbose_info}, switch => $switch, callback => $self->{callback}); #use cisco vlan membership mib to ascertain vlan
|
||||
my $trunktovlanmap = walkoid($session, '.1.3.6.1.4.1.9.9.46.1.6.1.1.5', silentfail => 1, verbose => $self->{show_verbose_info}, switch => $switch, callback => $self->{callback}); #for trunk ports, we are interested in the native vlan, so we need cisco vtp mib too
|
||||
@ -762,6 +843,10 @@ sub refresh_switch {
|
||||
$self->{nodeinfo}->{ $self->{switches}->{$switch}->{$portname} }->{vlans}->{$portname} = $trunktovlanmap->{$portid};
|
||||
}
|
||||
}
|
||||
#still needs output if there are no switchport defined on the nodes
|
||||
if (not defined $portname) {
|
||||
$vlans_to_check{'NA'} = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$vlans_to_check{'NA'} = 1;
|
||||
@ -784,9 +869,11 @@ sub refresh_switch {
|
||||
my $bridgetoifmap = walkoid($session, '.1.3.6.1.2.1.17.1.4.1.2', ciscowarn => $iscisco, verbose => $self->{show_verbose_info}, switch => $switch, callback => $self->{callback}); # Good for all switches
|
||||
if (not ref $bridgetoifmap or !keys %{$bridgetoifmap}) {
|
||||
xCAT::MsgUtils->message("S", "Error communicating with " . $session->{DestHost} . ": failed to get a valid response to BRIDGE-MIB request");
|
||||
if ($self->{collect_mac_info}) {
|
||||
$self->{macinfo}->{$switch}->{ErrorStr} = "Failed to get a valid response to BRIDGE-MIB request";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
# my $mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.4.3.1.2');
|
||||
my $mactoindexmap = walkoid($session, '.1.3.6.1.2.1.17.7.1.2.2.1.2', silentfail => 1, verbose => $self->{show_verbose_info}, switch => $switch, callback => $self->{callback});
|
||||
unless (defined($mactoindexmap)) { #if no qbridge defined, try bridge mib, probably cisco
|
||||
@ -795,9 +882,26 @@ sub refresh_switch {
|
||||
} #Ok, time to process the data
|
||||
if (not ref $mactoindexmap or !keys %{$mactoindexmap}) {
|
||||
xCAT::MsgUtils->message("S", "Error communicating with " . $session->{DestHost} . ": Unable to get MAC entries via either BRIDGE or Q-BRIDE MIB");
|
||||
if ($self->{collect_mac_info}) {
|
||||
$self->{macinfo}->{$switch}->{ErrorStr} = "Unable to get MAC entries via either BRIDGE or Q-BRIDE MIB";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
my $bridgeifvalid = 0;
|
||||
foreach (keys %$mactoindexmap) {
|
||||
my $index = $mactoindexmap->{$_};
|
||||
if (defined($bridgetoifmap->{$index})) {
|
||||
$bridgeifvalid = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
unless ($bridgeifvalid) {
|
||||
# create a dummy bridgetoifmap to cover switches that thing it should go straight to ifindex
|
||||
$bridgetoifmap = {};
|
||||
foreach (keys %$namemap) {
|
||||
$bridgetoifmap->{$_} = $_;
|
||||
}
|
||||
}
|
||||
if (defined($self->{collect_mac_info})) {
|
||||
my %index_to_mac = ();
|
||||
my %index_to_vlan = ();
|
||||
@ -807,8 +911,11 @@ sub refresh_switch {
|
||||
my $vlan = @tmp[0];
|
||||
my @mac = @tmp[ -6 .. -1 ];
|
||||
my $macstring = sprintf("%02x:%02x:%02x:%02x:%02x:%02x", @mac);
|
||||
push @{ $index_to_mac{$index} }, $macstring;
|
||||
push @{ $index_to_vlan{$index} }, $vlan;
|
||||
# Skip "permanent" ports
|
||||
if (!defined($mactostate->{$_}) || $mactostate->{$_} != 4) {
|
||||
push @{ $index_to_mac{$index} }, $macstring;
|
||||
push @{ $index_to_vlan{$index} }, $vlan;
|
||||
}
|
||||
}
|
||||
foreach my $boid (keys %$bridgetoifmap) {
|
||||
my $port_index = $boid;
|
||||
|
@ -2778,4 +2778,35 @@ sub gen_net_boot_params
|
||||
return $net_params;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
=head3 send_tcp_msg
|
||||
establish a tcp socket to the specified IP address and port, then send the specifid message via the socket
|
||||
Arguments:
|
||||
$destip : the destination IP address
|
||||
$destport: the destination TCP port
|
||||
$msg : the message to send
|
||||
Returns:
|
||||
0 on success, 1 on fail
|
||||
=cut
|
||||
#--------------------------------------------------------------------------------
|
||||
sub send_tcp_msg {
|
||||
my $self=shift;
|
||||
my $destip=shift;
|
||||
my $destport=shift;
|
||||
my $msg=shift;
|
||||
|
||||
my $sock = new IO::Socket::INET(
|
||||
PeerAddr => $destip,
|
||||
PeerPort => $destport,
|
||||
Timeout => '1',
|
||||
Proto => 'tcp'
|
||||
);
|
||||
if ($sock) {
|
||||
print $sock $msg;
|
||||
close($sock);
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
1;
|
||||
|
@ -226,7 +226,7 @@ qq{ link,ro - The file is readonly, and will be placed in tmpfs on the booted no
|
||||
'vncport' => 'Tracks the current VNC display port (currently not meant to be set',
|
||||
'textconsole' => 'Tracks the Psuedo-TTY that maps to the serial port or console of a VM',
|
||||
'powerstate' => "This flag is used by xCAT to track the last known power state of the VM.",
|
||||
'othersettings' => "This allows specifying a semicolon delimited list of key->value pairs to include in a vmx file of VMware or KVM. For partitioning on normal power machines, this option is used to specify the hugepage and/or bsr information, the value is like:'hugepage:1,bsr=2'. For KVM cpu pinning, this option is used to specify the physical cpu set on the host, the value is like:\"vcpupin:'0-15,^8'\",Its syntax is a comma separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed, the '-' denotes the range and the '^' denotes exclusive. For KVM memory binding, the value is like:'membind:0', restrict a guest to allocate memory from the specified set of NUMA nodes. For PCI passthrough, the value is like:'devpassthrough:pci_0001_01_00_0,pci_0000_03_00_0',the PCI devices are assigned to a virtual machine, and the virtual machine can use this I/O exclusively, the devices list are a list of PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.",
|
||||
'othersettings' => "This allows specifying a semicolon delimited list of key->value pairs to include in a vmx file of VMware or KVM. For partitioning on normal power machines, this option is used to specify the hugepage and/or bsr information, the value is like:'hugepage:1,bsr=2'. For KVM cpu pinning, this option is used to specify the physical cpu set on the host, the value is like:\"vcpupin:'0-15,^8'\",Its syntax is a comma separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed, the '-' denotes the range and the '^' denotes exclusive. For KVM memory binding, the value is like:'membind:0', restrict a guest to allocate memory from the specified set of NUMA nodes. For PCI passthrough, the value is like:'devpassthrough:pci_0001_01_00_0,pci_0000_03_00_0', the value for PCI device format also can be like:'devpassthrough:0001:01:00.1', the PCI devices are assigned to a virtual machine, and the virtual machine can use this I/O exclusively, the devices list are a list of PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.",
|
||||
'guestostype' => "This allows administrator to specify an identifier for OS to pass through to virtualization stack. Normally this should be ignored as xCAT will translate from nodetype.os rather than requiring this field be used\n",
|
||||
'beacon' => "This flag is used by xCAT to track the state of the identify LED with respect to the VM.",
|
||||
'datacenter' => "Optionally specify a datacenter for the VM to exist in (only applicable to VMWare)",
|
||||
@ -1243,7 +1243,19 @@ passed as argument rather than by table value',
|
||||
" Qualified Domain Name). Otherwise, the original behavior will be performed.\n\n" .
|
||||
" hierarchicalattrs: Table attributes(e.g. postscripts, postbootscripts) that will be\n" .
|
||||
" included hierarchically. Attribute values for all the node's groups\n" .
|
||||
" will be applied to the node in the groups' order except the repeat one.\n\n" .
|
||||
" will be applied to the node in the groups' order except the repeat one.\n" .
|
||||
" dbtracelevel: The trace level for the database access log. To activate this setting, please. \n".
|
||||
" restart xcatd or send HUP signal to the 'xcatd: DB Access' process, Like: .\n".
|
||||
" ps -ef | grep 'xcatd: DB Access' | grep -v grep | awk '{print \$2}' | xargs kill -HUP \n".
|
||||
" Currrent support values: \n" .
|
||||
" 0: disable the trace log for db \n" .
|
||||
" 1: trace the calls of database subroutines \n" .
|
||||
" 2: Besides the log from level 1, trace the event to build the cache for the table \n" .
|
||||
" 3: Besides the log from level 2, trace the event with cache hit \n" .
|
||||
" 4: Besides the log from level 3, trace the SQL statement for the db access \n" .
|
||||
" With this configuration, xcat will send the log to syslog very frequently, some of the \n".
|
||||
" log may be lost if imjournal is enabled by rsyslog. \n".
|
||||
" Please see https://github.com/xcat2/xcat-core/issues/3910 for the detail.\n\n" .
|
||||
" -----------------------\n" .
|
||||
"VIRTUALIZATION ATTRIBUTES\n" .
|
||||
" -----------------------\n" .
|
||||
@ -1563,14 +1575,15 @@ zvmivp => {
|
||||
If multiple ip addresses are associated with each NIC:
|
||||
<nic1>!<ext1>|<ext2>,<nic2>!<ext1>|<ext2>,..., for example, eth0!-eth0|-eth0-ipv6,ib0!-ib0|-ib0-ipv6.
|
||||
The xCAT object definition commands support to use nichostnamesuffixes.<nicname> as the sub attributes.
|
||||
Note: According to DNS rules a hostname must be a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-),and period (.). When you are specifying "nichostnamesuffixes" or "nicaliases" make sure the resulting hostnames will conform to this naming convention',
|
||||
nichostnameprefixes => 'Comma-separated list of hostname prefixes per NIC.
|
||||
|
||||
Note: According to DNS rules a hostname must be a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9) and minus sign (-). When you are specifying "nichostnamesuffixes" or "nicaliases" make sure the resulting hostnames will conform to this naming convention',
|
||||
nichostnameprefixes => 'Comma-separated list of hostname prefixes per NIC.
|
||||
If only one ip address is associated with each NIC:
|
||||
<nic1>!<ext1>,<nic2>!<ext2>,..., for example, eth0!eth0-,ib0!ib-
|
||||
If multiple ip addresses are associated with each NIC:
|
||||
<nic1>!<ext1>|<ext2>,<nic2>!<ext1>|<ext2>,..., for example, eth0!eth0-|eth0-ipv6i-,ib0!ib-|ib-ipv6-.
|
||||
The xCAT object definition commands support to use nichostnameprefixes.<nicname> as the sub attributes.
|
||||
Note: According to DNS rules a hostname must be a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-),and period (.). When you are specifying "nichostnameprefixes" or "nicaliases" make sure the resulting hostnames will conform to this naming convention',
|
||||
<nic1>!<ext1>|<ext2>,<nic2>!<ext1>|<ext2>,..., for example, eth0!eth0-|eth0-ipv6i-,ib0!ib-|ib-ipv6-.
|
||||
The xCAT object definition commands support to use nichostnameprefixes.<nicname> as the sub attributes.
|
||||
Note: According to DNS rules a hostname must be a text string up to 24 characters drawn from the alphabet (A-Z), digits (0-9) and minus sign (-). When you are specifying "nichostnameprefixes" or "nicaliases" make sure the resulting hostnames will conform to this naming convention',
|
||||
nictypes => 'Comma-separated list of NIC types per NIC. <nic1>!<type1>,<nic2>!<type2>, e.g. eth0!Ethernet,ib0!Infiniband. The xCAT object definition commands support to use nictypes.<nicname> as the sub attributes.',
|
||||
niccustomscripts => 'Comma-separated list of custom scripts per NIC. <nic1>!<script1>,<nic2>!<script2>, e.g. eth0!configeth eth0, ib0!configib ib0. The xCAT object definition commands support to use niccustomscripts.<nicname> as the sub attribute
|
||||
.',
|
||||
|
@ -71,6 +71,9 @@ require xCAT::Schema;
|
||||
require xCAT::NodeRange;
|
||||
use Text::Balanced qw(extract_bracketed);
|
||||
require xCAT::NotifHandler;
|
||||
use Time::HiRes qw/time/;
|
||||
use JSON;
|
||||
|
||||
|
||||
#The process id of the database worker
|
||||
# -1 db process has not been started, access db in direct access mode.
|
||||
@ -82,7 +85,19 @@ my $dbsockpath = "/var/run/xcat/dbworker.sock." . $$;
|
||||
my $exitdbthread;
|
||||
my $dbobjsforhandle;
|
||||
my $intendedpid;
|
||||
my $dbtracelevel;
|
||||
my %elapsed;
|
||||
|
||||
use constant BUILD_CACHE_TYPE => "build_cache";
|
||||
use constant CACHE_HIT_TYPE => "cache_hit";
|
||||
use constant START_TYPE => "start";
|
||||
use constant END_TYPE => "end";
|
||||
use constant START_SQL_TYPE => "start_sql";
|
||||
use constant END_SQL_TYPE => "end_sql";
|
||||
use constant INFO_TYPE => "info";
|
||||
|
||||
my %trace_level_mapping = (START_TYPE() => 1, END_TYPE() => 1, BUILD_CACHE_TYPE() => 2,
|
||||
CACHE_HIT_TYPE() => 3, START_SQL_TYPE() => 4, END_SQL_TYPE() => 4, INFO_TYPE() => 5);
|
||||
|
||||
sub dbc_call {
|
||||
my $self = shift;
|
||||
@ -155,6 +170,99 @@ sub dbc_submit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 _trace_log
|
||||
|
||||
Private helper function to write log message in json format
|
||||
|
||||
Arguments:
|
||||
$type: the type of the log content.
|
||||
$msg: the message content
|
||||
Returns:
|
||||
none
|
||||
|
||||
Error:
|
||||
none
|
||||
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub _trace_log
|
||||
{
|
||||
my ($type, $msg) = @_;
|
||||
if( $type eq START_TYPE || $type eq START_SQL_TYPE) {
|
||||
$elapsed{$trace_level_mapping{$type}} = time();
|
||||
}
|
||||
my %hash = ("type" => $type, "msg" => $msg);
|
||||
if($type eq END_TYPE || $type eq END_SQL_TYPE) {
|
||||
if (!$elapsed{$trace_level_mapping{$type}}) {
|
||||
return;
|
||||
}
|
||||
$hash{"elapsed"} = sprintf("%.5fs", time() - $elapsed{$trace_level_mapping{$type}});
|
||||
}
|
||||
xCAT::MsgUtils->message("S", "[DB Trace]: ".encode_json(\%hash));
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 trace_db
|
||||
|
||||
Add log entries to trace db acccess
|
||||
|
||||
Arguments:
|
||||
$type: the type of the log content. If it is "start", "start_sq"l, "end", "end_sql",
|
||||
a timer will be used to help calculate the elapsed time. Note, "start" and "end"
|
||||
or "start_sql" and "end_sql" must be used in pairs.
|
||||
$addon: the addon message.
|
||||
Returns:
|
||||
none
|
||||
|
||||
Error:
|
||||
none
|
||||
|
||||
Example:
|
||||
$self->trace_db("start"); # timer started.
|
||||
......
|
||||
$self->trace_db("end"); # print elapsed time.
|
||||
|
||||
$self->trace_db("start_sql"); # timer started.
|
||||
...... # statement to run the sql
|
||||
$self->trace_db("end_sql"); # print elapsed time.
|
||||
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub trace_db {
|
||||
my $self = shift;
|
||||
my ($type, $addon) = @_;
|
||||
if (!$dbtracelevel) {
|
||||
return;
|
||||
}
|
||||
if($dbworkerpid > 0) {
|
||||
return;
|
||||
}
|
||||
$type = INFO_TYPE if (!$type);
|
||||
if (!exists($trace_level_mapping{$type})) {
|
||||
xCAT::MsgUtils->message("S", "Unsupported db trace type $type");
|
||||
return;
|
||||
}
|
||||
if (($trace_level_mapping{$type} == 1) && (caller(2))[3] ne "xCAT::Table::handle_dbc_request") {
|
||||
# ignore internal calls
|
||||
return;
|
||||
}
|
||||
|
||||
if ($trace_level_mapping{$type} <= $dbtracelevel) {
|
||||
my $msg;
|
||||
$msg->{"table"} = $self->{tabname};
|
||||
$msg->{"method"} = (caller(1))[3];
|
||||
$msg->{"addon"} = $addon if $addon;
|
||||
_trace_log($type, $msg);
|
||||
}
|
||||
}
|
||||
|
||||
sub shut_dbworker {
|
||||
$dbworkerpid = -1; #For now, just turn off usage of the db worker
|
||||
#This was created as the monitoring framework shutdown code otherwise seems to have a race condition
|
||||
@ -188,6 +296,7 @@ sub init_dbworker {
|
||||
}
|
||||
unless ($dbworkerpid) {
|
||||
$intendedpid = $$;
|
||||
$dbtracelevel = xCAT::TableUtils->get_site_attribute("dbtracelevel");
|
||||
$SIG{CHLD} = sub { while (waitpid(-1, WNOHANG) > 0) { } }; #avoid zombies from notification framework
|
||||
#This process is the database worker, it's job is to manage database queries to reduce required handles and to permit cross-process caching
|
||||
$0 = "xcatd: DB Access";
|
||||
@ -199,6 +308,13 @@ sub init_dbworker {
|
||||
$SIG{ALRM} = sub { exit 0; };
|
||||
alarm(10);
|
||||
};
|
||||
$SIG{HUP} = sub {
|
||||
$dbtracelevel = xCAT::TableUtils->get_site_attribute("dbtracelevel");
|
||||
xCAT::MsgUtils->message("S", "dbtracelevel has been reloaded, current value is $dbtracelevel");
|
||||
foreach my $item ( keys %elapsed) {
|
||||
$elapsed{$item} = undef;
|
||||
}
|
||||
};
|
||||
unlink($dbsockpath);
|
||||
umask(0077);
|
||||
$dbworkersocket = IO::Socket::UNIX->new(Local => $dbsockpath, Type => SOCK_STREAM, Listen => 8192);
|
||||
@ -1453,8 +1569,10 @@ sub addAttribs
|
||||
$qstring = $qstring . "?,";
|
||||
}
|
||||
$qstring =~ s/,$/)/;
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $sth = $self->{dbh}->prepare($qstring);
|
||||
$sth->execute(@bind);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
|
||||
#$self->{dbh}->commit;
|
||||
|
||||
@ -1604,6 +1722,7 @@ sub setAttribs
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'setAttribs', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $pKeypairs = shift;
|
||||
my %keypairs = ();
|
||||
if ($pKeypairs != undef) { %keypairs = %{$pKeypairs}; }
|
||||
@ -1646,8 +1765,10 @@ sub setAttribs
|
||||
$qstring =~ s/ AND \z//;
|
||||
|
||||
#print "this is qstring1: $qstring\n";
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
$query->execute(@qargs);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
|
||||
#get the first row
|
||||
$data = $query->fetchrow_arrayref();
|
||||
@ -1720,13 +1841,17 @@ sub setAttribs
|
||||
}
|
||||
}
|
||||
$cmd =~ s/ AND \z//;
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $sth = $self->{dbh}->prepare($cmd);
|
||||
unless ($sth) {
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": Error attempting requested DB operation");
|
||||
return (undef, "Error attempting requested DB operation");
|
||||
}
|
||||
my $err = $sth->execute(@bind);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
if (not defined($err))
|
||||
{
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": ".$sth->errstr);
|
||||
return (undef, $sth->errstr);
|
||||
}
|
||||
$sth->finish;
|
||||
@ -1781,10 +1906,13 @@ sub setAttribs
|
||||
$qstring = $qstring . "?,";
|
||||
}
|
||||
$qstring =~ s/,$/)/;
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $sth = $self->{dbh}->prepare($qstring);
|
||||
my $err = $sth->execute(@bind);
|
||||
$self->trace_db(END_SQL_TYPE, $qstring);
|
||||
if (not defined($err))
|
||||
{
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": ". $sth->errstr);
|
||||
return (undef, $sth->errstr);
|
||||
}
|
||||
$sth->finish;
|
||||
@ -1803,6 +1931,7 @@ sub setAttribs
|
||||
xCAT::NotifHandler->notify($action, $self->{tabname},
|
||||
\@notif_data, \%new_notif_data);
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1850,6 +1979,7 @@ sub setAttribsWhere
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'setAttribsWhere', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $where_clause = shift;
|
||||
my $elems = shift;
|
||||
my $cols = "";
|
||||
@ -1864,8 +1994,10 @@ sub setAttribsWhere
|
||||
}
|
||||
my $qstring = "SELECT * FROM " . $self->{tabname} . " WHERE " . $where_clause;
|
||||
my @qargs = ();
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $query = $self->{dbh}->prepare($qstring);
|
||||
$query->execute(@qargs);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
|
||||
#get the first row
|
||||
my $data = $query->fetchrow_arrayref();
|
||||
@ -1903,10 +2035,13 @@ sub setAttribsWhere
|
||||
}
|
||||
chop($cols);
|
||||
my $cmd = "UPDATE " . $self->{tabname} . " set $cols where " . $where_clause;
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $sth = $self->{dbh}->prepare($cmd);
|
||||
my $err = $sth->execute(@bind);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
if (not defined($err))
|
||||
{
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": ".$sth->errstr);
|
||||
return (undef, $sth->errstr);
|
||||
}
|
||||
|
||||
@ -1923,6 +2058,7 @@ sub setAttribsWhere
|
||||
\@notif_data, \%new_notif_data);
|
||||
}
|
||||
$sth->finish;
|
||||
$self->trace_db(END_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1968,6 +2104,7 @@ sub setNodesAttribs {
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'setNodesAttribs', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $nodelist = shift;
|
||||
my $keyset = shift;
|
||||
my %cols = ();
|
||||
@ -2025,6 +2162,7 @@ sub setNodesAttribs {
|
||||
}
|
||||
$self->{dbh}->commit; #commit pending transactions
|
||||
$self->{dbh}->{AutoCommit} = $oldac; #restore autocommit semantics
|
||||
$self->trace_db(END_TYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2066,8 +2204,10 @@ sub setNodesAttribs {
|
||||
$qstring = "SELECT * FROM " . $self->{tabname} . " WHERE $dnodekey in (";
|
||||
$qstring .= '?, ' x scalar(@currnodes);
|
||||
$qstring =~ s/, $/)/;
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $query = $self->{dbh}->prepare($qstring);
|
||||
$query->execute(@currnodes);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
my $rec;
|
||||
while ($rec = $query->fetchrow_hashref()) {
|
||||
$updatenodes{ $rec->{$nodekey} } = 1;
|
||||
@ -2093,7 +2233,7 @@ sub setNodesAttribs {
|
||||
$bindhooks =~ s/, $//;
|
||||
$columns =~ s/, $//;
|
||||
my $instring = "INSERT INTO " . $self->{tabname} . " ($columns) VALUES ($bindhooks)";
|
||||
|
||||
$self->trace_db(START_SQL_TYPE, $instring);
|
||||
#print $instring;
|
||||
$insertsth = $self->{dbh}->prepare($instring);
|
||||
}
|
||||
@ -2105,7 +2245,9 @@ sub setNodesAttribs {
|
||||
foreach my $col (@orderedcols) {
|
||||
push @args, $hashrec->{$node}->{$col};
|
||||
}
|
||||
|
||||
$insertsth->execute(@args);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
}
|
||||
if (not $upsth and keys %updatenodes) { #prepare an insert statement since one will be needed
|
||||
my $upstring = "UPDATE " . $self->{tabname} . " set ";
|
||||
@ -2127,7 +2269,9 @@ sub setNodesAttribs {
|
||||
push @args, $hashrec->{$node}->{$col};
|
||||
}
|
||||
push @args, $node;
|
||||
$self->trace_db(START_SQL_TYPE, $upstring);
|
||||
$upsth->execute(@args);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
}
|
||||
}
|
||||
@currnodes = splice(@$nodelist, 0, $nodesatatime);
|
||||
@ -2135,6 +2279,7 @@ sub setNodesAttribs {
|
||||
$self->{dbh}->commit; #commit pending transactions
|
||||
$self->{dbh}->{AutoCommit} = $oldac; #restore autocommit semantics
|
||||
$self->_refresh_cache(); #cache is invalid, refresh
|
||||
$self->trace_db(END_TYPE);
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
@ -2170,6 +2315,7 @@ sub getNodesAttribs {
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getNodesAttribs', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $nodelist = shift;
|
||||
unless ($nodelist) { $nodelist = []; } #common to be invoked with undef seemingly
|
||||
my %options = ();
|
||||
@ -2216,6 +2362,7 @@ sub getNodesAttribs {
|
||||
if ($self->{tabname} ne 'nodelist') {
|
||||
$self->{nodelist}->{_use_cache} = 0;
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return $rethash;
|
||||
}
|
||||
|
||||
@ -2293,6 +2440,7 @@ sub _build_cache { #PRIVATE FUNCTION, PLEASE DON'T CALL DIRECTLY
|
||||
unless (grep /^$nodekey$/, @$attriblist) {
|
||||
push @$attriblist, $nodekey;
|
||||
}
|
||||
$self->trace_db(BUILD_CACHE_TYPE);
|
||||
my @tabcache = $self->getAllAttribs(@$attriblist);
|
||||
$self->{_tablecache} = \@tabcache;
|
||||
$self->{_nodecache} = {};
|
||||
@ -2316,7 +2464,153 @@ sub mknum {
|
||||
return $number;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 a2idx
|
||||
Description:
|
||||
Turns a character into a 1-indexed index
|
||||
Arguments:
|
||||
character: The character to convert
|
||||
Returns:
|
||||
The index
|
||||
Example:
|
||||
a2zidx('a') returns 1
|
||||
a2zidx('b') returns 2
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub a2idx {
|
||||
return ord(lc(shift)) - 96;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 a2zidx
|
||||
Description:
|
||||
Turns a character into a 0-indexed index
|
||||
Arguments:
|
||||
character: The character to convert
|
||||
Returns:
|
||||
The index
|
||||
Example:
|
||||
a2zidx('a') returns 0
|
||||
a2zidx('b') returns 1
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub a2zidx {
|
||||
return ord(lc(shift)) - 97;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 dim2idx
|
||||
Description:
|
||||
Converts dimensions into an index
|
||||
Arguments:
|
||||
dim_value: the value of the current dimension
|
||||
dim_total: the total number of elements in that dimension
|
||||
Returns:
|
||||
The index
|
||||
Example:
|
||||
A cluster has 4 rows
|
||||
A row has 10 racks
|
||||
A rack has 8 chassis
|
||||
A chassis has 8 nodes
|
||||
|
||||
Row 2, rack 3, chassis 4, node 5
|
||||
dim2idx(2, 10, 3, 8, 4, 8, 5) returns 797
|
||||
|
||||
Note the highest dimension is not needed and all values are 1-indexed
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub dim2idx {
|
||||
my $val = 0; # value to return
|
||||
my $fn = 0; # math function to apply, 0 is add, 1 is multiply
|
||||
while (defined(my $element = shift)) {
|
||||
$val += $element - 1 if !$fn;
|
||||
$val *= $element if $fn;
|
||||
$fn = 1 - $fn;
|
||||
}
|
||||
return $val + 1;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 skip
|
||||
Description:
|
||||
Return an index with certain values skipped
|
||||
Arguments:
|
||||
index: The initial index
|
||||
skips: Index values to skip
|
||||
format start[:count][,start[:count]...]
|
||||
Returns:
|
||||
The updated index
|
||||
Example:
|
||||
skip(10, '3') returns 9
|
||||
skip(10, '3:2') returns 8
|
||||
skip(10, '3:2,6') returns 7
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub skip {
|
||||
my $idx = my $val = shift;
|
||||
my $skips = shift;
|
||||
foreach my $element (split /,/, $skips) {
|
||||
my ($start, $count) = split /:/, $element;
|
||||
$count = 1 if ! defined($count);
|
||||
if ($idx >= $start) {
|
||||
if ($idx < $start + $count) {return -1;}
|
||||
$val-= $count;
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
=head3 ipadd
|
||||
Description:
|
||||
Add to an IP address. Useful when you cross octets.
|
||||
Optionally skip addresses at the start and end of octets (like .0 or .255).
|
||||
Technically those are valid IP addresses, but sometimes software makes
|
||||
poor assumptions about which broadcast and gateway addresses.
|
||||
Arguments:
|
||||
b1: Starting IP address first octet
|
||||
b2: Starting IP address second octet
|
||||
b3: Starting IP address third octet
|
||||
b4: Starting IP address fourth octet
|
||||
toadd: Value to add to the starting address
|
||||
skipstart: Number of addresses to skip at the start of the last octet
|
||||
skipend: Number of addresses to skip at the end of the last octet
|
||||
Returns:
|
||||
The new IP address
|
||||
Example:
|
||||
ipadd(10, 10, 10, 10, 0, 0, 0) returns 10.10.10.10
|
||||
ipadd(10, 10, 10, 10, 10, 0, 0) returns 10.10.10.20
|
||||
ipadd(10, 10, 10, 10, 245, 0, 0) returns 10.10.10.255
|
||||
ipadd(10, 10, 10, 10, 246, 0, 0) returns 10.10.11.0
|
||||
=cut
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
sub ipadd {
|
||||
use integer;
|
||||
my ($b1, $b2, $b3, $b4, $toadd, $skipstart, $skipend) = @_;
|
||||
my $offset = ($b4 >= $skipstart) ? $b4 - $skipstart : 0;
|
||||
$b3 += ($offset + $toadd) / (256-$skipstart-$skipend);
|
||||
$b4 = ($offset + $toadd) % (256-$skipstart-$skipend) + $skipstart;
|
||||
return join('.', $b1, $b2, $b3, $b4);
|
||||
}
|
||||
|
||||
$evalcpt->share('&mknum');
|
||||
$evalcpt->share('&a2idx');
|
||||
$evalcpt->share('&a2zidx');
|
||||
$evalcpt->share('&dim2idx');
|
||||
$evalcpt->share('&skip');
|
||||
$evalcpt->share('&ipadd');
|
||||
$evalcpt->permit('require');
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
@ -2443,6 +2737,7 @@ sub getNodeAttribs
|
||||
#db worker scope
|
||||
return dbc_call($self, 'getNodeAttribs', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
|
||||
if (!defined($self->{dbh})) {
|
||||
xCAT::MsgUtils->message("S", "xcatd: DBI is missing, Please check the db access process.");
|
||||
@ -2521,6 +2816,7 @@ sub getNodeAttribs
|
||||
}
|
||||
}
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return wantarray ? @data : $data[0];
|
||||
}
|
||||
|
||||
@ -2862,7 +3158,6 @@ sub getNodeAttribs_nosub_returnany
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return @results;
|
||||
}
|
||||
|
||||
@ -2901,6 +3196,7 @@ sub getAllEntries
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getAllEntries', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
|
||||
if (!defined($self->{dbh})) {
|
||||
xCAT::MsgUtils->message("S", "xcatd: DBI is missing, Please check the db access process.");
|
||||
@ -2915,12 +3211,15 @@ sub getAllEntries
|
||||
my $disable = &delimitcol("disable");
|
||||
if ($allentries) { # get all lines
|
||||
$query = $self->{dbh}->prepare('SELECT * FROM ' . $self->{tabname});
|
||||
$self->trace_db(START_SQL_TYPE, 'SELECT * FROM ' . $self->{tabname});
|
||||
} else { # get only enabled lines
|
||||
my $qstring = 'SELECT * FROM ' . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data)
|
||||
@ -2933,6 +3232,7 @@ sub getAllEntries
|
||||
push @rets, $data;
|
||||
}
|
||||
$query->finish();
|
||||
$self->trace_db(END_TYPE);
|
||||
return \@rets;
|
||||
}
|
||||
|
||||
@ -2995,6 +3295,7 @@ sub getAllAttribsWhere
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getAllAttribsWhere', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $clause = shift;
|
||||
my $whereclause;
|
||||
my @attribs = @_;
|
||||
@ -3011,8 +3312,10 @@ sub getAllAttribsWhere
|
||||
# delimit the disable column based on the DB
|
||||
my $disable = &delimitcol("disable");
|
||||
$query2 = 'SELECT * FROM ' . $self->{tabname} . ' WHERE (' . $whereclause . ") and ($disable is NULL or $disable in ('0','no','NO','No','nO'))";
|
||||
$self->trace_db(START_SQL_TYPE, $query2);
|
||||
$query = $self->{dbh}->prepare($query2);
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
my %newrow = ();
|
||||
@ -3040,6 +3343,7 @@ sub getAllAttribsWhere
|
||||
}
|
||||
}
|
||||
$query->finish();
|
||||
$self->trace_db(END_TYPE);
|
||||
return @results;
|
||||
}
|
||||
|
||||
@ -3078,6 +3382,7 @@ sub getAllNodeAttribs
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getAllNodeAttribs', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $attribq = shift;
|
||||
my $hashretstyle = shift;
|
||||
my %options = @_;
|
||||
@ -3098,8 +3403,10 @@ sub getAllNodeAttribs
|
||||
my $qstring = 'SELECT ' . $dnodekey . ' FROM '
|
||||
. $self->{tabname}
|
||||
. " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
xCAT::NodeRange::retain_cache(1);
|
||||
|
||||
unless ($options{prefetchcache}) {
|
||||
@ -3171,6 +3478,7 @@ sub getAllNodeAttribs
|
||||
$self->{_use_cache} = 0;
|
||||
$self->{nodelist}->{_use_cache} = 0;
|
||||
$query->finish();
|
||||
$self->trace_db(END_TYPE);
|
||||
if ($hashretstyle) {
|
||||
return $rethash;
|
||||
} else {
|
||||
@ -3212,9 +3520,10 @@ sub getAllAttribs
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getAllAttribs', @_);
|
||||
}
|
||||
|
||||
$self->trace_db(START_TYPE);
|
||||
if (!defined($self->{dbh})) {
|
||||
xCAT::MsgUtils->message("S", "xcatd: DBI is missing, Please check the db access process.");
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": DBI is missing");
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -3244,8 +3553,10 @@ sub getAllAttribs
|
||||
}
|
||||
if (@results)
|
||||
{
|
||||
$self->trace_db(END_TYPE);
|
||||
return @results; #return wantarray ? @results : $results[0];
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -3254,10 +3565,12 @@ sub getAllAttribs
|
||||
my $query;
|
||||
my $qstring = "SELECT * FROM " . $self->{tabname}
|
||||
. " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
|
||||
#print $query;
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE, $qstring);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
my %newrow = ();
|
||||
@ -3274,6 +3587,7 @@ sub getAllAttribs
|
||||
}
|
||||
}
|
||||
$query->finish();
|
||||
$self->trace_db(END_TYPE);
|
||||
return @results;
|
||||
}
|
||||
|
||||
@ -3317,6 +3631,7 @@ sub delEntries
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'delEntries', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $keyref = shift;
|
||||
my @all_keyparis;
|
||||
my %keypairs;
|
||||
@ -3361,10 +3676,10 @@ sub delEntries
|
||||
$qstring =~ s/\(\)//;
|
||||
$qstring =~ s/ OR \z//;
|
||||
|
||||
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
my $query = $self->{dbh}->prepare($qstring);
|
||||
$query->execute(@qargs);
|
||||
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
#prepare the notification data
|
||||
#put the column names at the very front
|
||||
push(@notif_data, $query->{NAME});
|
||||
@ -3399,8 +3714,10 @@ sub delEntries
|
||||
}
|
||||
$delstring =~ s/\(\)//;
|
||||
$delstring =~ s/ OR \z//;
|
||||
$self->trace_db(START_SQL_TYPE, $delstring);
|
||||
my $stmt = $self->{dbh}->prepare($delstring);
|
||||
$stmt->execute(@stargs);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
$stmt->finish;
|
||||
|
||||
$self->_refresh_cache(); #cache is invalid, refresh
|
||||
@ -3411,7 +3728,7 @@ sub delEntries
|
||||
}
|
||||
@pieces = splice(@all_keyparis, 0, $record_num);
|
||||
}
|
||||
|
||||
$self->trace_db(END_TYPE);
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
@ -3450,6 +3767,7 @@ sub getAttribs
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getAttribs', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
|
||||
#my $key = shift;
|
||||
#my $keyval = shift;
|
||||
@ -3510,8 +3828,11 @@ sub getAttribs
|
||||
}
|
||||
if (@results)
|
||||
{
|
||||
$self->trace_db(END_TYPE);
|
||||
$self->trace_db(CACHE_HIT_TYPE);
|
||||
return wantarray ? @results : $results[0];
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -3544,11 +3865,14 @@ sub getAttribs
|
||||
$statement .= "(" . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO'))";
|
||||
|
||||
#print "This is my statement: $statement \n";
|
||||
$self->trace_db(START_SQL_TYPE, $statement);
|
||||
my $query = $self->{dbh}->prepare($statement);
|
||||
unless (defined $query) {
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": undef");
|
||||
return undef;
|
||||
}
|
||||
$query->execute(@exeargs);
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
my $data;
|
||||
while ($data = $query->fetchrow_hashref())
|
||||
{
|
||||
@ -3569,8 +3893,10 @@ sub getAttribs
|
||||
$query->finish();
|
||||
if (@return)
|
||||
{
|
||||
$self->trace_db(END_TYPE);
|
||||
return wantarray ? @return : $return[0];
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -3610,10 +3936,13 @@ sub getTable
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getTable', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my @return;
|
||||
my $statement = 'SELECT * FROM ' . $self->{tabname};
|
||||
$self->trace_db(START_SQL_TYPE, $statement);
|
||||
my $query = $self->{dbh}->prepare($statement);
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
my $data;
|
||||
while ($data = $query->fetchrow_hashref())
|
||||
{
|
||||
@ -3631,8 +3960,10 @@ sub getTable
|
||||
$query->finish();
|
||||
if (@return)
|
||||
{
|
||||
$self->trace_db(END_TYPE);
|
||||
return @return;
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -4089,6 +4420,7 @@ sub writeAllEntries
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'writeAllEntries', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $filename = shift;
|
||||
my $fh;
|
||||
my $rc = 0;
|
||||
@ -4097,6 +4429,7 @@ sub writeAllEntries
|
||||
unless (open($fh, " > $filename")) {
|
||||
my $msg = "Unable to open $filename for write \n.";
|
||||
`logger -p local4.err -t xcat $msg`;
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": ".$msg);
|
||||
return 1;
|
||||
}
|
||||
my $query;
|
||||
@ -4112,9 +4445,11 @@ sub writeAllEntries
|
||||
|
||||
# delimit the disable column based on the DB
|
||||
my $disable = &delimitcol("disable");
|
||||
$self->trace_db(START_SQL_TYPE, 'SELECT * FROM ' . $self->{tabname});
|
||||
$query = $self->{dbh}->prepare('SELECT * FROM ' . $self->{tabname});
|
||||
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data)
|
||||
@ -4128,6 +4463,7 @@ sub writeAllEntries
|
||||
}
|
||||
$query->finish();
|
||||
CORE::close($fh);
|
||||
$self->trace_db(END_TYPE);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
@ -4170,6 +4506,7 @@ sub writeAllAttribsWhere
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'writeAllAttribsWhere', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $clause = shift;
|
||||
my $filename = shift;
|
||||
my $whereclause;
|
||||
@ -4184,6 +4521,7 @@ sub writeAllAttribsWhere
|
||||
unless (open($fh, " > $filename")) {
|
||||
my $msg = "Unable to open $filename for write \n.";
|
||||
`logger -p local4.err -t xcat $msg`;
|
||||
$self->trace_db(END_TYPE, "LINE ".__LINE__.": ".$msg);
|
||||
return 1;
|
||||
}
|
||||
my $header;
|
||||
@ -4201,8 +4539,10 @@ sub writeAllAttribsWhere
|
||||
# delimit the disable column based on the DB
|
||||
my $disable = &delimitcol("disable");
|
||||
$query2 = 'SELECT * FROM ' . $self->{tabname} . ' WHERE (' . $whereclause . ") and ($disable is NULL or $disable in ('0','no','NO','No','nO'))";
|
||||
$self->trace_db(START_SQL_TYPE, $query2);
|
||||
$query = $self->{dbh}->prepare($query2);
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data) {
|
||||
@ -4216,6 +4556,7 @@ sub writeAllAttribsWhere
|
||||
}
|
||||
$query->finish();
|
||||
CORE::close($fh);
|
||||
$self->trace_db(END_TYPE);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
@ -4291,6 +4632,7 @@ sub getMAXMINEntries
|
||||
if ($dbworkerpid > 0) {
|
||||
return dbc_call($self, 'getMAXMINEntries', @_);
|
||||
}
|
||||
$self->trace_db(START_TYPE);
|
||||
my $attr = shift;
|
||||
my $rets;
|
||||
my $query;
|
||||
@ -4304,9 +4646,11 @@ sub getMAXMINEntries
|
||||
} else {
|
||||
$qstring = "SELECT MAX($attr) FROM " . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
}
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data)
|
||||
@ -4328,9 +4672,11 @@ sub getMAXMINEntries
|
||||
} else {
|
||||
$qstring = "SELECT MIN($attr) FROM " . $self->{tabname} . " WHERE " . $disable . " is NULL or " . $disable . " in ('0','no','NO','No','nO')";
|
||||
}
|
||||
$self->trace_db(START_SQL_TYPE, $qstring);
|
||||
$query = $self->{dbh}->prepare($qstring);
|
||||
|
||||
$query->execute();
|
||||
$self->trace_db(END_SQL_TYPE);
|
||||
while (my $data = $query->fetchrow_hashref())
|
||||
{
|
||||
foreach (keys %$data)
|
||||
@ -4344,6 +4690,7 @@ sub getMAXMINEntries
|
||||
last; # better be only one value for min
|
||||
}
|
||||
}
|
||||
$self->trace_db(END_TYPE);
|
||||
return $rets;
|
||||
}
|
||||
1;
|
||||
|
@ -85,7 +85,9 @@ my %usage = (
|
||||
OpenPOWER (OpenBMC) specific:
|
||||
rvitals noderange [temp|voltage|wattage|fanspeed|power|altitude|all]
|
||||
MIC specific:
|
||||
rvitals noderange {thermal|all}",
|
||||
rvitals noderange {thermal|all}
|
||||
pdu specific:
|
||||
rvitals noderange ",
|
||||
"reventlog" =>
|
||||
"Usage: reventlog <noderange> [all [-s]|clear|<number of entries to retrieve> [-s]] [-V|--verbose]
|
||||
reventlog [-h|--help|-v|--version]",
|
||||
@ -143,7 +145,7 @@ my %usage = (
|
||||
rspconfig <noderange> [garp=<number of 1/2 second>]
|
||||
rspconfig <noderange> [userid=<userid> username=<username> password=<password>]
|
||||
OpenBMC specific:
|
||||
rspconfig <noderange> [ip|netmask|gateway|vlan]
|
||||
rspconfig <noderange> [ip|netmask|gateway|hostname|vlan]
|
||||
iDataplex specific:
|
||||
rspconfig <noderange> [thermprofile]
|
||||
rspconfig <noderange> [thermprofile=<two digit number from chassis>]
|
||||
@ -329,7 +331,7 @@ my %usage = (
|
||||
pdudiscover [<noderange>|--range ipranges] [-r|-x|-z] [-w] [-V|--verbose] [--setup]",
|
||||
"switchdiscover" =>
|
||||
"Usage: switchdiscover [-h|--help|-v|--version]
|
||||
switchdiscover [<noderange>|--range ipranges] [-s scan_methods] [-r|-x|-z] [-w] [-V|--verbose] [--setup]",
|
||||
switchdiscover [<noderange>|--range ipranges] [-s scan_methods] [-c community] [-r|-x|-z] [-w] [-V|--verbose] [--setup]",
|
||||
"switchprobe" =>
|
||||
"Usage: switchprobe [<noderange>] [-V|--verbose | -c|--check]",
|
||||
"makentp" =>
|
||||
@ -345,10 +347,13 @@ my %usage = (
|
||||
rflash <noderange> -p <rpm_directory> [--activate {disruptive|deferred}] [-d <data_directory>]
|
||||
rflash <noderange> [--commit | --recover] [-V|--verbose]
|
||||
rflash <noderange> [--bpa_acdl]
|
||||
PPC64LE (using IPMI Management) specific:
|
||||
rflash <noderange> [-c|--check] [--retry=<count>] [-V] [<hpm_file>|-d=<data_directory>]
|
||||
PPC64LE (using OpenBMC Management) specific:
|
||||
rflash <noderange> [-c|--check] [-l|--list] [-a|--activate] [-u|--upload] [-d|--delete] [<tar_file>|<image_id>]",
|
||||
OpenPOWER BMC specific (using IPMI):
|
||||
rflash <noderange> [<hpm_file_path>|-d <data_directory>] [-c|--check] [--retry=<count>] [-V]
|
||||
rflash <noderange> --recover <bmc_file_path>
|
||||
OpenPOWER OpenBMC specific:
|
||||
rflash <noderange> {[-c|--check] | [-l|--list]}
|
||||
rflash <noderange> <tar_file_path> {[-c|--check] | [-a|--activate] | [-u|--upload]}
|
||||
rflash <noderange> <image_id> {[-a|--activate] | [-d|--delete]}",
|
||||
"mkhwconn" =>
|
||||
"Usage:
|
||||
mkhwconn [-h|--help]
|
||||
|
@ -19,6 +19,7 @@ use lib "$::XCATROOT/lib/perl";
|
||||
# needing it to avoid reprocessing of user tables ( ExtTab.pm) for each command call
|
||||
use POSIX qw(ceil);
|
||||
use File::Path;
|
||||
#use Data::Dumper;
|
||||
use Socket;
|
||||
use strict;
|
||||
use Symbol;
|
||||
@ -42,7 +43,6 @@ require xCAT::InstUtils;
|
||||
#require xCAT::NetworkUtils;
|
||||
require xCAT::Schema;
|
||||
|
||||
#require Data::Dumper;
|
||||
require xCAT::NodeRange;
|
||||
require xCAT::Version;
|
||||
require DBI;
|
||||
@ -575,6 +575,13 @@ sub isLinux
|
||||
sub Version
|
||||
{
|
||||
my $version = shift;
|
||||
|
||||
#force reload the xCAT::Version in case the perl-xcat is upgraded but xcatd is not restarted
|
||||
if($INC{'xCAT/Version.pm'}){
|
||||
delete $INC{'xCAT/Version.pm'};
|
||||
}
|
||||
|
||||
require xCAT::Version;
|
||||
$version = xCAT::Version->Version();
|
||||
return $version;
|
||||
}
|
||||
@ -4911,4 +4918,5 @@ sub acquire_lock_imageop {
|
||||
return (0,$lock);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
@ -18,7 +18,10 @@ our %global_mac_identity = (
|
||||
"fc:cf:62" => "BNT G8124 switch",
|
||||
"7c:fe:90" => "Mellanox IB switch",
|
||||
"cc:37:ab" => "Edgecore Networks Switch",
|
||||
"8c:ea:1b" => "Edgecore Networks Switch"
|
||||
"8c:ea:1b" => "Edgecore Networks Switch",
|
||||
"a8:2b:b5" => "Edgecore Networks Switch",
|
||||
"3c:2c:99" => "Edgecore Networks Switch",
|
||||
"70:72:cf" => "Edgecore Networks Switch"
|
||||
);
|
||||
|
||||
#the hash to lookup switch type with vendor
|
||||
|
@ -23,13 +23,24 @@ use Getopt::Long;
|
||||
use POSIX qw(:signal_h :errno_h :sys_wait_h);
|
||||
use Thread qw(yield);
|
||||
|
||||
|
||||
$::onecli = 0;
|
||||
if ($iam =~ /pasu/) {
|
||||
$::utilcmd = '/opt/lenovo/toolscenter/asu/asu64';
|
||||
$::utilcmd = '/opt/lenovo/onecli/asu';
|
||||
$::onecli = 1;
|
||||
if (!-x $::utilcmd) {
|
||||
$::onecli = 0;
|
||||
$::utilcmd = '/opt/lenovo/toolscenter/asu/asu64';
|
||||
}
|
||||
if (!-x $::utilcmd) {
|
||||
$::utilcmd = '/opt/ibm/toolscenter/asu/asu64';
|
||||
}
|
||||
} elsif ($iam =~ /piflash/) {
|
||||
$::utilcmd = '/opt/xcat/sbin/iflash64 --unattended';
|
||||
$::utilcmd = '/opt/lenovo/onecli/iflash64';
|
||||
if (!-x $::utilcmd) {
|
||||
$::utilcmd = '/opt/xcat/sbin/iflash64';
|
||||
}
|
||||
$::utilcmd .= ' --unattended'
|
||||
}
|
||||
my $interface;
|
||||
my $username;
|
||||
@ -198,7 +209,17 @@ sub processoutput { #This way, one arbiter handles output, no interrupting
|
||||
$line !~ /Licensed Materials - Property of Lenovo/i &&
|
||||
$line !~ /\(C\) Copyright IBM Corp. \d+-\d+ All Rights Reserved/i &&
|
||||
$line !~ /\(C\) Copyright Lenovo Corp. \d+-\d+ All Rights Reserved/i &&
|
||||
$line !~ /Connected to IMM at IP address/i)) {
|
||||
$line !~ /Connected to IMM at IP address/i &&
|
||||
$line !~ /Lenovo ASU/i &&
|
||||
$line !~ /^\s*$/i &&
|
||||
$line !~ /Lenovo ToolsCenterSuite CLI/i &&
|
||||
$line !~ /Lenovo XClarity Essentials OneCLI/i &&
|
||||
$line !~ /Invoking SHOW command .../i &&
|
||||
$line !~ /Invoking SET command .../i &&
|
||||
$line !~ /Connected to BMC by IP address/i &&
|
||||
$line !~ /Succeeded running the command /i &&
|
||||
$line !~ /Based on module version /i &&
|
||||
$line !~ /Succeed running command /i)) {
|
||||
print $nodehdl{$readyh} . ": " . $line . "\n";
|
||||
}
|
||||
}
|
||||
@ -225,6 +246,9 @@ sub utilnode {
|
||||
} else {
|
||||
foreach my $a (@_) { $args .= ' ' . xCAT::Utils->quote($a); }
|
||||
}
|
||||
if ($::onecli and $bmc =~ /:/) {
|
||||
$bmc = "[$bmc]";
|
||||
}
|
||||
my $cmd = "$::utilcmd $args --host '$bmc' --user '$username' --password '$passwd' 2>&1 |";
|
||||
if ($::VERBOSE) { print "forking $cmd\n"; }
|
||||
my $pid = open($$out, $cmd);
|
||||
|
@ -21,7 +21,6 @@ use Getopt::Long;
|
||||
use xCAT::MsgUtils;
|
||||
use xCAT::Utils;
|
||||
use xCAT::Client;
|
||||
use xCAT::NodeRange;
|
||||
use Cwd;
|
||||
use strict;
|
||||
|
||||
@ -72,12 +71,6 @@ if(grep m/^-c|--console$/,@ARGV){
|
||||
}
|
||||
|
||||
my $noderange = $cmdref->{noderange}->[0]; # save the noderange
|
||||
my @noderange=xCAT::NodeRange::noderange($noderange);
|
||||
|
||||
if($bname eq "rinstall" and $startconsole==1 and scalar @noderange!=1 ){
|
||||
xCAT::MsgUtils->message("E", "Error: rinstall -c/--console can only be run against one node! Please use winstall -c/--console for multiple nodes.");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Allow to print server information when -V/--verbose
|
||||
foreach (reverse(@ARGV)) {
|
||||
|
@ -8,6 +8,7 @@ use xCAT::Client;
|
||||
use Getopt::Long;
|
||||
use strict;
|
||||
my %output;
|
||||
my %outputhdrs;
|
||||
|
||||
my $option;
|
||||
my $printcount;
|
||||
@ -45,7 +46,7 @@ sub fillerup {
|
||||
}
|
||||
}
|
||||
if ($individual) {
|
||||
foreach my $node (keys %output) {
|
||||
foreach my $node (sort { $a <=> $b or $a cmp $b } keys %output) {
|
||||
print "====================================\n";
|
||||
print "$node\n";
|
||||
print "====================================\n";
|
||||
@ -63,6 +64,11 @@ foreach my $output (keys %collated) {
|
||||
unless ($option) {
|
||||
xCAT::Client::submit_request($cmdref, \&fillerup);
|
||||
}
|
||||
$outputhdrs{$nodes} = $output;
|
||||
}
|
||||
foreach my $hdr (sort { $a <=> $b or $a cmp $b } keys %outputhdrs) {
|
||||
$nodes = $hdr;
|
||||
my $output = $outputhdrs{$hdr};
|
||||
print "====================================\n";
|
||||
print "$nodes\n";
|
||||
print "====================================\n";
|
||||
|
@ -8,7 +8,7 @@ B<bmcdiscover> [B<-?>|B<-h>|B<--help>]
|
||||
|
||||
B<bmcdiscover> [B<-v>|B<--version>]
|
||||
|
||||
B<bmcdiscover> [B<-s> I<scan_method>] [B<-u> I<bmc_user>] [B<-p> I<bmc_passwd>] [B<-z>] [B<-w>] B<--range> I<ip_ranges>
|
||||
B<bmcdiscover> [B<--sn> I<SN_nodename>] [B<-s> I<scan_method>] [B<-u> I<bmc_user>] [B<-p> I<bmc_passwd>] [B<-z>] [B<-w>] B<--range> I<ip_ranges>
|
||||
|
||||
B<bmcdiscover> B<-u> I<bmc_user> B<-p> I<bmc_passwd> B<-i> I<bmc_ip> B<--check>
|
||||
|
||||
@ -33,6 +33,10 @@ Note: The scan method currently support is B<nmap>.
|
||||
|
||||
Specify one or more IP ranges acceptable to nmap. IP range can be hostnames, IP addresses, networks, etc. A single IP address (10.1.2.3) or an IP range (10.1.2.0/24) can be specified. If the range is very large, the B<bmcdiscover> command may take a long time to return.
|
||||
|
||||
=item B<--sn>
|
||||
|
||||
Specify one or more service nodes on which bmcdiscover will run. In hierarchical cluster, the MN may not be able to access the BMC of CN directly, but SN can. With this option, bmcdiscover will be dispatched to the specified SNs. Then, the nodename of the service node that 'bmcdiscover' is running on will be set to the 'servicenode' attribute of the discovered BMC node.
|
||||
|
||||
=item B<-s>
|
||||
|
||||
Scan method (The only supported scan method at this time is B<nmap>)
|
||||
@ -90,19 +94,34 @@ Display version information
|
||||
|
||||
Note: Input for IP range can be in the form: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254.
|
||||
|
||||
2. To get all BMSs in IP range "10.4.22-23.100-254", displayed in xCAT stanza format:
|
||||
2. To get all BMCs in IP range "10.4.22-23.100-254", displayed in xCAT stanza format:
|
||||
|
||||
bmcdiscover -s nmap --range "10.4.22-23.100-254" -z
|
||||
|
||||
3. Discover the BMCs and write the discovered-node definitions into the xCAT database and write out the stanza foramt to the console:
|
||||
3. To discover BMCs through sn01:
|
||||
|
||||
bmcdiscover --sn sn01 -s nmap --range "10.4.22-23.100-254" -z
|
||||
|
||||
Output is similar to:
|
||||
|
||||
node-70e28414291b:
|
||||
objtype=node
|
||||
groups=all
|
||||
bmc=10.4.22.101
|
||||
cons=openbmc
|
||||
mgt=openbmc
|
||||
servicenode=sn01
|
||||
conserver=sn01
|
||||
|
||||
4. Discover the BMCs and write the discovered-node definitions into the xCAT database and write out the stanza foramt to the console:
|
||||
|
||||
bmcdiscover -s nmap --range "10.4.22-23.100-254" -w -z
|
||||
|
||||
4. To check if the username or password is correct against the BMC:
|
||||
5. To check if the username or password is correct against the BMC:
|
||||
|
||||
bmcdiscover -i 10.4.23.254 -u USERID -p PASSW0RD --check
|
||||
|
||||
5. Get BMC IP Address source, DHCP Address or static Address
|
||||
6. Get BMC IP Address source, DHCP Address or static Address
|
||||
|
||||
bmcdiscover -i 10.4.23.254 -u USERID -p PASSW0RD --ipsource
|
||||
|
||||
|
@ -24,11 +24,17 @@ B<rflash> I<noderange> I<http_directory>
|
||||
|
||||
=head2 OpenPOWER BMC specific (using IPMI):
|
||||
|
||||
B<rflash> I<noderange> [I<hpm_file_path> | B<-d=>I<data_directory>] [B<-c>|B<--check>] [B<--retry=>I<count>] [B<-V>]
|
||||
B<rflash> I<noderange> [I<hpm_file_path> | B<-d> I<data_directory>] [B<-c>|B<--check>] [B<--retry=>I<count>] [B<-V>]
|
||||
|
||||
B<rflash> I<noderange> B<--recover> I<bmc_file_path>
|
||||
|
||||
=head2 OpenPOWER OpenBMC specific :
|
||||
|
||||
B<rflash> I<noderange> [I<tar_file_path> | I<image_id>] [B<-c>|B<--check>] [B<-a>|B<--activate>] [B<-l>|B<--list>] [B<-u>|B<--upload>] [B<-d>|B<--delete>]
|
||||
B<rflash> I<noderange> {[B<-c>|B<--check>] | [B<-l>|B<--list>]}
|
||||
|
||||
B<rflash> I<noderange> I<tar_file_path> {[B<-c>|B<--check>] | [B<-a>|B<--activate>] | [B<-u>|B<--upload>]}
|
||||
|
||||
B<rflash> I<noderange> I<image_id> {[B<-a>|B<--activate>] | [B<-d>|B<--delete>]}
|
||||
|
||||
=head1 B<Description>
|
||||
|
||||
@ -111,9 +117,11 @@ Specifies the directory where the packages are located.
|
||||
|
||||
=item B<-d> I<data_directory>
|
||||
|
||||
PPC (without HMC, using Direct FSP Management) specific:
|
||||
|
||||
Specifies the directory where the raw data from rpm packages for each CEC/Frame are located. The default directory is /tmp. The option is only used in Direct FSP/BPA Management.
|
||||
|
||||
=item B<-d=>I<data_directory>
|
||||
OpenPOWER BMC specific (using IPMI):
|
||||
|
||||
Used for IBM Power S822LC for Big Data systems only. Specifies the directory where the B<pUpdate> utility and at least one of BMC or PNOR update files are located. The utility and update files can be downloaded from FixCentral.
|
||||
|
||||
@ -127,15 +135,21 @@ Used to commit the flash image in the temporary side of the chip to the permanen
|
||||
|
||||
=item B<--recover>
|
||||
|
||||
PPC (with HMC) and PPC (without HMC, using Direct FSP Management) specific:
|
||||
|
||||
Used to recover the flash image in the permanent side of the chip to the temporary side for both managed systems and power subsystems.
|
||||
|
||||
OpenPOWER BMC specific (using IPMI):
|
||||
|
||||
Used for IBM Power S822LC for Big Data systems only. Used to recover the BMC with a BMC image downloaded from FixCentral.
|
||||
|
||||
=item B<--retry=>I<count>
|
||||
|
||||
Specify number of times to retry the update if failure is detected. Default value is 2. Value of 0 can be used to indicate no retries.
|
||||
|
||||
=item B<-a|--activate>
|
||||
|
||||
Activate update image. Image id must be specified.
|
||||
Activate update image. Image id or update file must be specified.
|
||||
|
||||
=item B<-l|--list>
|
||||
|
||||
@ -201,7 +215,12 @@ Print verbose message to rflash log file (/var/log/xcat/rflash/fs3.log) when upd
|
||||
=item 6.
|
||||
To update the firmware on IBM Power S822LC for Big Data machine specify the node name and the file path of the data directory containing pUpdate utility and BMC and/or PNOR update files:
|
||||
|
||||
rflash briggs01 -d=/root/supermicro/OP825
|
||||
rflash briggs01 -d /root/supermicro/OP825
|
||||
|
||||
=item 7.
|
||||
To update the firmware on the OpenBMC machine, specify the firmare update file to upload and activate:
|
||||
|
||||
rflash p9euh02 -a /tmp/witherspoon.pnor.squashfs.tar
|
||||
|
||||
=back
|
||||
|
||||
|
@ -5,14 +5,14 @@ B<rsetboot> - Sets the boot device to be used for BMC-based servers for the next
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<rsetboot> I<noderange> {B<hd>|B<net>|B<cd>|B<default>|B<stat>} [B<-u>] [B<-p>]
|
||||
B<rsetboot> I<noderange> [B<hd>|B<net>|B<cd>|B<default>|B<stat>] [B<-u>] [B<-p>]
|
||||
|
||||
B<rsetboot> [B<-h>|B<--help>|B<-v>|B<--version>]
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<rsetboot> sets the boot media and boot mode that should be used on the next boot of the specified nodes. After the nodes are booted with the specified device and boot mode (e.g. via L<rpower(1)|rpower.1>), the nodes will return to using the default boot device specified in the BIOS. Currently this command is only supported for IPMI nodes.
|
||||
B<rsetboot> sets the boot media and boot mode that should be used on the next boot of the specified nodes. After the nodes are booted with the specified device and boot mode (e.g. via L<rpower(1)|rpower.1>), the nodes will return to using the default boot device specified in the BIOS.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
@ -64,6 +64,10 @@ Display the next-boot value for nodes 14-56 and 70-203:
|
||||
|
||||
rsetboot node[14-56],node[70-203] stat
|
||||
|
||||
Or:
|
||||
|
||||
rsetboot node[14-56],node[70-203]
|
||||
|
||||
=item 3.
|
||||
|
||||
Restore the next-boot value for these nodes back to their default set in the BIOS:
|
||||
|
@ -24,7 +24,7 @@ B<rspconfig> I<noderange> B<garp>=I<time>
|
||||
|
||||
=head2 OpenBMC specific:
|
||||
|
||||
B<rspconfig> I<noderange> {B<ip>|B<netmask>|B<gateway>|B<vlan>|B<sshcfg>}
|
||||
B<rspconfig> I<noderange> {B<ip>|B<netmask>|B<gateway>|B<hostname>|B<vlan>|B<sshcfg>}
|
||||
|
||||
=head2 MPA specific:
|
||||
|
||||
@ -300,6 +300,10 @@ Set CEC/BPA system names to the names in xCAT DB or the input name.
|
||||
|
||||
Select the policy for I/O Adapter Enlarged Capacity. This option controls the size of PCI memory space allocated to each PCI slot.
|
||||
|
||||
=item B<hostname>
|
||||
|
||||
Get or set hostname on the service processor.
|
||||
|
||||
=item B<vlan>
|
||||
|
||||
Get or set vlan ID. For get vlan ID, if vlan is not enabled, 'BMC VLAN disabled' will be outputed. For set vlan ID, the valid value are [1-4096].
|
||||
|
@ -10,7 +10,7 @@ B<switchdiscover [-h| --help]>
|
||||
|
||||
B<switchdiscover [-v| --version]>
|
||||
|
||||
B<switchdiscover> [I<noderange> | B<--range> I<ip_ranges>] B<[-V] [-w][-r|-x|-z][-s> I<scan_methods> B<--setup>]
|
||||
B<switchdiscover> [I<noderange> | B<--range> I<ip_ranges>] B<[-V] [-w][-r|-x|-z][-s> I<scan_methods>] [B<--setup>] [B<-c> I<community>]
|
||||
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ To view all the switches defined in the xCAT database use B<lsdef -w "nodetype=s
|
||||
|
||||
For lldp method, make sure that lldpd package is installed and lldpd is running on the xCAT management node. lldpd comes from xcat-dep package or you can get it from http://vincentbernat.github.io/lldpd/installation.html.
|
||||
|
||||
For snmp method, make sure that snmpwalk command is installed and snmp is enabled for switches. To install snmpwalk, "yum install net-snmp-utils" for redhat and sles, "apt-get install snmp" for Ubuntu.
|
||||
For snmp method, make sure that snmpwalk command is installed and snmp is enabled for switches. To install snmpwalk, "yum install net-snmp-utils" for redhat and sles, "apt-get install snmp" for Ubuntu. The switchdiscover command only check the switches with default community string, if user already configured switch with other commmunity string, need to pass in with B<-c> option for switchdiscover command to be able to discover.
|
||||
|
||||
|
||||
=head1 OPTIONS
|
||||
@ -87,6 +87,10 @@ Stanza formatted output.
|
||||
|
||||
Process switch-based switch discovery. Update discovered switch's ip address, hostname and enable snmpv3 configuration based on the predefined switch.
|
||||
|
||||
=item B<-c>
|
||||
|
||||
User defined community string for snmp scan.
|
||||
|
||||
=back
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
@ -13,13 +13,16 @@ DIR=`dirname $0`
|
||||
DIR=`readlink -f $DIR`
|
||||
BUILDARCH=`uname -m`
|
||||
|
||||
#For Openpower
|
||||
if [ $BUILDARCH = "ppc64le" ]; then
|
||||
BUILDARCH="ppc64"
|
||||
fi
|
||||
rpmdev-setuptree
|
||||
|
||||
#For Openpower
|
||||
if [ -z $1 ]; then
|
||||
HOSTOS="fedora26"
|
||||
if [ $BUILDARCH = "ppc64le" ]; then
|
||||
HOSTOS="Pegas1.0"
|
||||
BUILDARCH="ppc64"
|
||||
else
|
||||
HOSTOS="fedora26"
|
||||
fi
|
||||
fi
|
||||
|
||||
# get the input files for dracut in the right place
|
||||
@ -42,7 +45,7 @@ if [ $BUILDARCH = "x86_64" ]; then
|
||||
sed -i 's/\/lib64\/libpanel.so.5//' $DRACUTMODDIR/install
|
||||
sed -i 's/\/lib64\/libmenu.so.5//' $DRACUTMODDIR/install
|
||||
sed -i 's/\/lib64\/libsysfs.so.2//' $DRACUTMODDIR/install
|
||||
sed -i 's/\/usr\/sbin\/iprconfig//' $DRACUTMODDIR/install
|
||||
sed -i '/\/usr\/sbin\/iprconfig/ d' $DRACUTMODDIR/install
|
||||
sed -i '/hwdb.bin/ d' $DRACUTMODDIR/install
|
||||
sed -i 's/instmods ipr//' $DRACUTMODDIR/installkernel
|
||||
fi
|
||||
@ -54,7 +57,7 @@ if [ "$HOSTOS" = "mcp" ]; then
|
||||
sed -i 's/dmidecode//' $DRACUTMODDIR/install
|
||||
sed -i 's/\/lib\/ld-linux.so.2/\/usr\/lib64\/ld-2.17.so/' $DRACUTMODDIR/install
|
||||
sed -i 's/\/lib64\/libsysfs.so.2//' $DRACUTMODDIR/install
|
||||
sed -i 's/\/usr\/sbin\/iprconfig//' $DRACUTMODDIR/install
|
||||
sed -i '/\/usr\/sbin\/iprconfig/ d' $DRACUTMODDIR/install
|
||||
else
|
||||
sed -i 's/\/lib\/ld-linux.so.2/\/usr\/lib64\/ld-linux-x86-64.so.2/' $DRACUTMODDIR/install
|
||||
fi
|
||||
@ -105,6 +108,12 @@ if [ "$HOSTOS" = "mcp" ]; then
|
||||
# For ppc64 platform, needs to remove some files,
|
||||
# # and some files are in different directories
|
||||
elif [ $BUILDARCH = "ppc64" ]; then
|
||||
if [ "$HOSTOS" = "Pegas1.0" ]; then
|
||||
sed -i 's/ mkreiserfs//' $DRACUTMODDIR/install
|
||||
sed -i 's/ reiserfstune//' $DRACUTMODDIR/install
|
||||
sed -i 's/ vconfig//' $DRACUTMODDIR/install
|
||||
sed -i 's/ ntp-wait//' $DRACUTMODDIR/install
|
||||
fi
|
||||
sed -i 's/ efibootmgr//' $DRACUTMODDIR/install
|
||||
sed -i 's/ dmidecode//' $DRACUTMODDIR/install
|
||||
sed -i 's/\/lib\/terminfo\/l\/linux/\/usr\/share\/terminfo\/l\/linux/g' $DRACUTMODDIR/install
|
||||
|
@ -4,7 +4,7 @@ Version: %{?version:%{version}}%{!?version:%(cat Version)}
|
||||
Release: %{?release:%{release}}%{!?release:%(cat Release)}
|
||||
Epoch: 1
|
||||
AutoReq: false
|
||||
Requires: ipmitool screen btrfs-progs lldpad rpm-build compat-libstdc++-33 mstflint xfsprogs nc reiserfs-utils
|
||||
Requires: ipmitool screen btrfs-progs lldpad rpm-build mstflint xfsprogs nc rpmdevtools libstdc++-devel pciutils bridge-utils ntp ntp-perl iprutils psmisc mdadm bind-utils dosfstools usbutils libusbx
|
||||
Prefix: /opt/xcat
|
||||
AutoProv: false
|
||||
|
||||
|
@ -293,9 +293,6 @@ logger -s -t $log_label -p local4.info "Detected LAN channel $LANCHAN"
|
||||
|
||||
let idev=NUMBMCS
|
||||
if [ $IPCFGMETHOD="static" ]; then
|
||||
if [ ! -z "$ISOPENBMC" ]; then
|
||||
let idev=0
|
||||
fi
|
||||
while [ $idev -gt 0 ]; do
|
||||
let idev=idev-1
|
||||
TRIES=0
|
||||
@ -370,45 +367,43 @@ else
|
||||
done
|
||||
fi
|
||||
|
||||
let idev=0
|
||||
for b in $BMCVLAN; do
|
||||
if [ "$BMCVLAN" = off ]; then
|
||||
TRIES=0
|
||||
# Set VLAN for the current channel
|
||||
while ! ipmitool -d $idev lan set $LANCHAN vlan id $b; do
|
||||
while ! ipmitool raw 0xc 1 $LANCHAN 0x14 0 0; do
|
||||
snooze
|
||||
let TRIES=TRIES+1
|
||||
if [ $TRIES -gt $TIMEOUT ]; then
|
||||
if [ $TRIES -gt $TIMEOUT ]; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
let idev=idev+1
|
||||
done
|
||||
|
||||
else
|
||||
let idev=0
|
||||
for b in $BMCVLAN; do
|
||||
TRIES=0
|
||||
# Set VLAN for the current channel
|
||||
while ! ipmitool -d $idev lan set $LANCHAN vlan id $b; do
|
||||
snooze
|
||||
let TRIES=TRIES+1
|
||||
if [ $TRIES -gt $TIMEOUT ]; then
|
||||
break;
|
||||
fi
|
||||
done
|
||||
let idev=idev+1
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# update the node status to 'bmcready' for openbmc, no more configuration is needed.
|
||||
if [ ! -z "$ISOPENBMC" ]; then
|
||||
# To enable network configuration for openbmc
|
||||
TRIES=0
|
||||
bmc_config_rc=0
|
||||
# Set Channel Access to apply network setting
|
||||
#while ! ipmitool -d 0 lan set $LANCHAN access on; do
|
||||
while ! ipmitool -d 0 raw 0x06 0x40 $LANCHAN 0x42 0x44 > /dev/null; do
|
||||
snooze
|
||||
let TRIES=TRIES+1
|
||||
if [ $TRIES -gt $TIMEOUT ]; then
|
||||
bmc_config_rc=1
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
ipmitool -d 0 lan set $LANCHAN access on
|
||||
# update the node status to 'bmcready'
|
||||
if [ ! -z "$XCATMASTER" ]; then
|
||||
if [ "$bmc_config_rc" = "0" ]; then
|
||||
# Wait for some time for the new network setting is ready
|
||||
snooze
|
||||
# Wait for some time for the new network setting is ready
|
||||
snooze
|
||||
if ipmitool lan print 1 | grep $BMCIP >/dev/null; then
|
||||
updateflag.awk $XCATMASTER 3002 "installstatus bmcready"
|
||||
else
|
||||
else
|
||||
updateflag.awk $XCATMASTER 3002 "installstatus failed"
|
||||
fi
|
||||
fi
|
||||
|
@ -99,13 +99,17 @@ if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86
|
||||
if [ -z "$MTM" ]; then
|
||||
FRU=`ipmitool fru print 0`
|
||||
if [ $? -eq 0 ]; then
|
||||
MTM=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {m=$2} /Product Name/ {n=$2} END {print m":"n}'`
|
||||
m=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {print $2}'`
|
||||
n=`echo "$FRU" | awk -F': ' '/Product Name/ {print $2}'`
|
||||
if [ -z "$n" -o "$n" == "NONE" ]; then
|
||||
n=`echo "$FRU" | awk -F': ' '/Product Part Number/ {print $2}'`
|
||||
fi
|
||||
else
|
||||
logger -s -t $log_label -p local4.warning "Couldn't find MTM information in FRU, falling back to DMI (MTMS-based discovery may fail)"
|
||||
m=`cat /sys/devices/virtual/dmi/id/sys_vendor`
|
||||
n=`cat /sys/devices/virtual/dmi/id/product_name`
|
||||
MTM="$m:$n"
|
||||
fi
|
||||
MTM="$m:$n"
|
||||
fi
|
||||
SERIAL=`cat /sys/devices/virtual/dmi/id/product_serial`
|
||||
fi
|
||||
@ -117,7 +121,6 @@ if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86
|
||||
UUID=`sed -e 's/\(..\)\(..\)\(..\)\(..\)-\(..\)\(..\)-\(..\)\(..\)/\4\3\2\1-\6\5-\8\7/' /sys/devices/virtual/dmi/id/product_uuid`
|
||||
|
||||
elif [ -r /proc/device-tree/model ]; then #POWER
|
||||
#MTM=`cat /proc/device-tree/model |awk -F, '{print $2}'`
|
||||
MTM=`cat /proc/device-tree/model -vT | sed -e 's/^.*,//' | sed -e 's/^[\t ]*//'| sed -e 's/[\t ]*\^@//'`
|
||||
CPUCOUNT=`cat /proc/cpuinfo |grep -e "^cpu\s*:"|wc -l`
|
||||
PLATFORM=`cat /proc/cpuinfo | grep -e "^platform\s*:" | awk '{print \$3}'`
|
||||
@ -131,25 +134,14 @@ elif [ -r /proc/device-tree/model ]; then #POWER
|
||||
UUID=unknown
|
||||
|
||||
fi
|
||||
#CPUCOUNT=`cat /proc/cpuinfo |grep "model name"|wc -l`
|
||||
|
||||
# The MEMORY will look like this: 32868920
|
||||
MEMORY=`cat /proc/meminfo |grep MemTotal|awk '{printf "%.0fMB\n", $2/1024}'`
|
||||
# The MEMORY will look like this: 32GiB
|
||||
#MEMORY=`lshw -C memory -short |grep "System Memory"|awk -F' ' '{print $3}'`
|
||||
|
||||
# The DISKSIZE will look like this: /dev/sda:250GB,/dev/sdb:250GB
|
||||
#DISKSIZE=`lshw -C disk -short |grep disk |awk -F' ' '{print $2":"$4}'|sed 'N;s/\n/,/'`
|
||||
# The DISKSIZE will look like this: sdb:250GB,sda:250GB
|
||||
DISKSIZE=`cat /proc/partitions |grep -e "sd.\>" |awk -F' ' '{printf "%s:%.0fGB\n", $4, $3*0.000001024}' |sed 'N;s/\n/,/'`
|
||||
|
||||
#UUID=`sed -e 's/\(..\)\(..\)\(..\)\(..\)-\(..\)\(..\)-\(..\)\(..\)/\4\3\2\1-\6\5-\8\7/' /sys/devices/virtual/dmi/id/product_uuid`
|
||||
#grep "model name" /proc/cpuinfo | while read line; do #to avoid pulling in tail, we do a goofy thing
|
||||
# echo $line > /tmp/cpumod
|
||||
#done
|
||||
#CPUTYPE=`cat /tmp/cpumod|awk -F':' '{print $2}'|sed -e 's/^ //'`
|
||||
|
||||
logger -s -t $log_label -p local4.info "Beginning echo infomation to discovery packet file..."
|
||||
logger -s -t $log_label -p local4.info "Beginning echo information to discovery packet file..."
|
||||
echo '<xcatrequest>' > /tmp/discopacket
|
||||
echo "<command>findme</command>" >> /tmp/discopacket
|
||||
echo "<sequential>1</sequential>" >> /tmp/discopacket
|
||||
@ -167,10 +159,12 @@ fi
|
||||
|
||||
flag_mtm=`echo '$MTM' | sed 's/0//g'`
|
||||
if [ $flag_mtm ] && [ "$MTM" != "unknown" ]; then
|
||||
MTM=`echo $MTM | sed 's/\.//g'`
|
||||
echo "<mtm>$MTM</mtm>" >> /tmp/discopacket
|
||||
fi
|
||||
flag_serial=`echo '$SERIAL' | sed 's/0//g'`
|
||||
if [ $flag_serial ] && [ "$SERIAL" != "unknown" ]; then
|
||||
SERIAL=`echo $SERIAL | sed 's/\.//g'`
|
||||
echo "<serial>$SERIAL</serial>" >> /tmp/discopacket
|
||||
fi
|
||||
if [ "$PLATFORM" != "unknown" ]; then
|
||||
|
@ -8,8 +8,6 @@ log_label="xcat.genesis.doxcat"
|
||||
# Start rsyslogd and log into a local file specified in /etc/rsyslog.conf
|
||||
# Later, once xCAT MN is known, dhclient-script will change
|
||||
# rsyslog.conf file to send log entries to xCAT MN
|
||||
logger -s -t $log_label -p local4.info "Starting syslog..."
|
||||
ls /var/run/
|
||||
RSYSLOGD_VERSION=`rsyslogd -v | grep "rsyslogd" | cut -d" " -f2 | cut -d"." -f1`
|
||||
|
||||
# if syslog is running and there's a pid file, kill it before restarting syslogd
|
||||
@ -357,6 +355,10 @@ while :; do
|
||||
logger -s -t $log_label -p local4.info "Running nextdestiny $XCATMASTER:$XCATPORT..."
|
||||
/bin/nextdestiny $XCATMASTER:$XCATPORT
|
||||
logger -s -t $log_label -p local4.info "nextdestiny - Complete."
|
||||
elif [ "$dest" = osimage ]; then
|
||||
logger -s -t $log_label -p local4.info "Running nextdestiny $XCATMASTER:$XCATPORT..."
|
||||
destiny=`/bin/nextdestiny $XCATMASTER:$XCATPORT`
|
||||
logger -s -t $log_label -p local4.info "nextdestiny - Complete."
|
||||
elif [ "$dest" = runcmd ]; then
|
||||
logger -s -t $log_label -p local4.info "Running nextdestiny $XCATMASTER:$XCATPORT..."
|
||||
destiny=`/bin/nextdestiny $XCATMASTER:$XCATPORT`
|
||||
|
@ -182,7 +182,7 @@ sub is_static_ip {
|
||||
if ($os =~ /redhat/) {
|
||||
my $output1 = `cat /etc/sysconfig/network-scripts/ifcfg-$nic 2>&1 |grep -i IPADDR`;
|
||||
my $output2 = `cat /etc/sysconfig/network-scripts/ifcfg-$nic 2>&1 |grep -i BOOTPROTO`;
|
||||
$rst = 1 if (($output1 =~ /$ip/) && ($output2 =~ /static/i));
|
||||
$rst = 1 if (($output1 =~ /$ip/) && ($output2 =~ /static|none/i));
|
||||
} elsif ($os =~ /sles/) {
|
||||
my $output1 = `cat /etc/sysconfig/network/ifcfg-$nic 2>&1 |grep -i IPADDR`;
|
||||
my $output2 = `cat /etc/sysconfig/network/ifcfg-$nic 2>&1 |grep -i BOOTPROTO`;
|
||||
|
354
xCAT-probe/scripts/dbstats.py
Normal file
354
xCAT-probe/scripts/dbstats.py
Normal file
@ -0,0 +1,354 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# !/usr/bin/python
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
BUF_SIZE = 8192
|
||||
|
||||
|
||||
class Reader(object):
|
||||
def __init__(self, file):
|
||||
self.f_size = os.stat(file).st_size
|
||||
self.f_pos = self.f_size
|
||||
self.file = file
|
||||
self.buf_list = []
|
||||
self.remain = None
|
||||
self.f = None
|
||||
|
||||
def open(self):
|
||||
if self.f is None:
|
||||
self.f = open(self.file)
|
||||
|
||||
def close(self):
|
||||
if self.f is not None:
|
||||
self.f.close()
|
||||
self.f = None
|
||||
|
||||
def __enter__(self):
|
||||
self.open()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.close()
|
||||
|
||||
def _read(self):
|
||||
if self.f_pos == 0:
|
||||
return None
|
||||
|
||||
size = BUF_SIZE
|
||||
if self.f_pos - BUF_SIZE >= 0:
|
||||
self.f.seek(self.f_pos - BUF_SIZE)
|
||||
else:
|
||||
self.f.seek(0)
|
||||
size = self.f_pos - 0
|
||||
buf = self.f.read(size)
|
||||
if self.remain is not None:
|
||||
self.buf_list = (buf + self.remain).split('\n')
|
||||
else:
|
||||
self.buf_list = buf.split('\n')
|
||||
if size == BUF_SIZE:
|
||||
self.remain = self.buf_list[0]
|
||||
self.buf_list = self.buf_list[1:]
|
||||
else:
|
||||
self.remain = None
|
||||
self.f_pos -= size
|
||||
|
||||
return self.buf_list
|
||||
|
||||
def get_next(self):
|
||||
ret = self._get_next()
|
||||
if ret is not None:
|
||||
return ret
|
||||
|
||||
while self._read() is not None:
|
||||
ret = self._get_next()
|
||||
if ret is not None:
|
||||
return ret
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class CommandReader(Reader):
|
||||
def __init__(self, file):
|
||||
super(CommandReader, self).__init__(file)
|
||||
self.cmd = {}
|
||||
|
||||
def _get_next(self):
|
||||
""" Extract data from the commands log file of xcat
|
||||
Format::
|
||||
|
||||
[Date] 2017-09-04 17:52:10
|
||||
[ClientType] cli
|
||||
[Request] xdsh c910f04x35v07 'echo "nameserver 9.0.2.1" >> /etc/resolv.conf'
|
||||
[Response]
|
||||
[ElapsedTime] 0 s
|
||||
:return: command dict if found, None if not found
|
||||
"""
|
||||
for i, b in enumerate(self.buf_list[::-1]):
|
||||
if b.find('[ElapsedTime]') == 0:
|
||||
self.cmd['elapsed'] = float(b.split(' ')[1])
|
||||
elif b.find('[Request]') == 0:
|
||||
self.cmd['request'] = " ".join(
|
||||
b.rstrip().split(' ')[1:]).strip().replace(',', ' ')
|
||||
elif b.find('[Date]') == 0:
|
||||
temp = b.split(' ')
|
||||
self.cmd['date'] = '%s %s' % (temp[-2], temp[-1])
|
||||
|
||||
if all(k in self.cmd for k in ('date', 'request', 'elapsed')):
|
||||
cmd = self.cmd
|
||||
self.cmd = {}
|
||||
self.buf_list = self.buf_list[0:len(self.buf_list) - i - 1]
|
||||
return cmd
|
||||
return None
|
||||
|
||||
|
||||
class DBTraceReader(Reader):
|
||||
def __init__(self, file):
|
||||
super(DBTraceReader, self).__init__(file)
|
||||
self.year = str(time.localtime().tm_year)
|
||||
|
||||
def _get_next(self):
|
||||
"""Extract information from syslog file of xcat
|
||||
Format::
|
||||
|
||||
Sep 4 22:16:38 c910f04x12v02 xcat[6692]: [DB Trace]: {"msg":{"table":"nodegroup","method":"xCAT::Table::getAllEntries"},"type":"end_sql","elapsed":"0.00042s"}
|
||||
|
||||
:return: A dict contains the time stamp and db dict if db trace log is
|
||||
found. None if nothing about db trace log found.
|
||||
"""
|
||||
for i, b in enumerate(self.buf_list[::-1]):
|
||||
pos = b.find('[DB Trace]:')
|
||||
if pos == -1:
|
||||
continue
|
||||
date = b[0:15]
|
||||
conv = time.strptime('%s %s' % (self.year, date),
|
||||
"%Y %b %d %H:%M:%S")
|
||||
# TODO: the year value is not included in the current syslog
|
||||
try:
|
||||
ret = {'stamp': int(time.mktime(conv)),
|
||||
'db': json.loads(b[pos + 12:])}
|
||||
except ValueError:
|
||||
if b.find('message repeated') != -1:
|
||||
# syslog will add [ ] around the json message.
|
||||
ret = {'stamp': int(time.mktime(conv)),
|
||||
'db': json.loads(b[pos + 12:-1])}
|
||||
else:
|
||||
raise
|
||||
|
||||
self.buf_list = self.buf_list[0:len(self.buf_list) - i - 1]
|
||||
return ret
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class TimeStamp(object):
|
||||
def __init__(self, kwargs):
|
||||
if 'date' in kwargs:
|
||||
a = time.strptime(kwargs['date'], "%Y-%m-%d %H:%M:%S")
|
||||
self.start = int(time.mktime(a))
|
||||
else:
|
||||
raise
|
||||
if 'elapsed' in kwargs:
|
||||
self.end = self.start + int(kwargs['elapsed']) + 1
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
class Analysis(object):
|
||||
def __init__(self, command_log_file, cluster_log_file):
|
||||
self.command_log_file = command_log_file
|
||||
self.cluster_log_file = cluster_log_file
|
||||
|
||||
def _stat(self, record, data):
|
||||
elapsed = 0
|
||||
if 'elapsed' in data:
|
||||
# elapsed = float('%.3f' % float(data['elapsed'][:-1]))
|
||||
elapsed = float(data['elapsed'][:-1])
|
||||
if data['type'] == 'end_sql':
|
||||
if data['msg']['method'].startswith('xCAT::Table::get'):
|
||||
record['get_sql_time'] += elapsed
|
||||
elif data['msg']['method'].startswith('xCAT::Table::set'):
|
||||
record['set_sql_time'] += elapsed
|
||||
elif data['msg']['method'].startswith('xCAT::Table::del'):
|
||||
record['del_sql_time'] += elapsed
|
||||
elif data['type'] == 'end':
|
||||
if data['msg']['method'].startswith('xCAT::Table::get'):
|
||||
record['get_sub_time'] += elapsed
|
||||
elif data['msg']['method'].startswith('xCAT::Table::set'):
|
||||
record['set_sub_time'] += elapsed
|
||||
elif data['msg']['method'].startswith('xCAT::Table::del'):
|
||||
record['del_sub_time'] += elapsed
|
||||
elif data['type'] == 'start_sql':
|
||||
if data['msg']['method'].startswith('xCAT::Table::get'):
|
||||
if data['msg']['table'] not in record['get_tables']:
|
||||
record['get_tables'][data['msg']['table']] = 1
|
||||
else:
|
||||
record['get_tables'][data['msg']['table']] += 1
|
||||
elif data['msg']['method'].startswith('xCAT::Table::set'):
|
||||
if data['msg']['table'] not in record['set_tables']:
|
||||
record['set_tables'][data['msg']['table']] = 1
|
||||
else:
|
||||
record['set_tables'][data['msg']['table']] += 1
|
||||
elif data['msg']['method'].startswith('xCAT::Table::del'):
|
||||
if data['msg']['table'] not in record['del_tables']:
|
||||
record['del_tables'][data['msg']['table']] = 1
|
||||
else:
|
||||
record['del_tables'][data['msg']['table']] += 1
|
||||
elif data['type'] == 'build_cache':
|
||||
if data['msg']['table'] not in record['build_cache']:
|
||||
record['build_cache'][data['msg']['table']] = 1
|
||||
else:
|
||||
record['build_cache'][data['msg']['table']] += 1
|
||||
elif data['type'] == 'cache_hit':
|
||||
if data['msg']['table'] not in record['cache_hit']:
|
||||
record['cache_hit'][data['msg']['table']] = 1
|
||||
else:
|
||||
record['cache_hit'][data['msg']['table']] += 1
|
||||
|
||||
def process(self, latest, specific_cmd):
|
||||
if specific_cmd is not None:
|
||||
latest = None
|
||||
|
||||
self._print_header()
|
||||
with CommandReader(self.command_log_file) as cmd_reader:
|
||||
cmd = cmd_reader.get_next()
|
||||
trace = None
|
||||
index = 0
|
||||
db_reader = DBTraceReader(self.cluster_log_file)
|
||||
db_reader.open()
|
||||
while cmd is not None:
|
||||
if specific_cmd is not None and not cmd['request'].startswith(
|
||||
specific_cmd):
|
||||
cmd = cmd_reader.get_next()
|
||||
continue
|
||||
|
||||
stamp = TimeStamp(cmd)
|
||||
if trace is None:
|
||||
trace = db_reader.get_next()
|
||||
|
||||
while trace and trace['stamp'] > stamp.end:
|
||||
trace = db_reader.get_next()
|
||||
key = '%s(%s)' % (cmd['request'], cmd['date'])
|
||||
|
||||
record = {'command': key,
|
||||
'elapsed': cmd['elapsed'],
|
||||
'get_sql_time': float(0),
|
||||
'set_sql_time': float(0),
|
||||
'del_sql_time': float(0),
|
||||
'set_sub_time': float(0),
|
||||
'get_sub_time': float(0),
|
||||
'del_sub_time': float(0),
|
||||
'get_tables': {},
|
||||
'set_tables': {},
|
||||
'del_tables': {},
|
||||
'build_cache': {},
|
||||
'cache_hit': {}}
|
||||
|
||||
while trace and trace['stamp'] >= stamp.start:
|
||||
self._stat(record, trace['db'])
|
||||
trace = db_reader.get_next()
|
||||
|
||||
self._print_csv(record)
|
||||
index += 1
|
||||
if latest is not None and index == latest:
|
||||
break
|
||||
cmd = cmd_reader.get_next()
|
||||
db_reader.close()
|
||||
|
||||
def _print_header(self):
|
||||
print("command,elapsed(precision: 1s),"
|
||||
"get_sub_time(s),set_sub_time(s),del_sub_time(s),"
|
||||
"get_sql_time(s),set_sql_time(s),del_sql_time(s),"
|
||||
"build_cache(times),cache_hit(times),"
|
||||
"get_tables(times),set_tables(times),del_tables(times)")
|
||||
|
||||
def _print_csv(self, record):
|
||||
print("%(command)s,%(elapsed)f,"
|
||||
"%(get_sub_time)f,%(set_sub_time)f,%(del_sub_time)f,"
|
||||
"%(get_sql_time)f,%(set_sql_time)f,%(del_sql_time)f,"
|
||||
"%(build_cache)s,%(cache_hit)s,"
|
||||
"%(get_tables)s,%(set_tables)s,%(del_tables)s\n" %
|
||||
{'command': record['command'],
|
||||
'elapsed': record['elapsed'],
|
||||
'get_sub_time': float('%.3f' % record['get_sub_time']),
|
||||
'set_sub_time': float('%.3f' % record['set_sub_time']),
|
||||
'del_sub_time': float('%.3f' % record['del_sub_time']),
|
||||
'get_sql_time': float('%.3f' % record['get_sql_time']),
|
||||
'set_sql_time': float('%.3f' % record['set_sql_time']),
|
||||
'del_sql_time': float('%.3f' % record['del_sql_time']),
|
||||
'build_cache': self._format_dict(record['build_cache']),
|
||||
'cache_hit': self._format_dict(record['cache_hit']),
|
||||
'get_tables': self._format_dict(record['get_tables']),
|
||||
'set_tables': self._format_dict(record['set_tables']),
|
||||
'del_tables': self._format_dict(record['del_tables'])})
|
||||
|
||||
def _format_list(self, a):
|
||||
return " ".join(a)
|
||||
|
||||
def _format_dict(self, d):
|
||||
ret = []
|
||||
for k, v in d.items():
|
||||
if type(v) is list:
|
||||
ret.append('%s:[%s]', k, " ".join(v))
|
||||
elif type(v) is str or type(v) is int:
|
||||
ret.append('%s:%s' % (k, str(v)))
|
||||
return " ".join(ret)
|
||||
|
||||
|
||||
class StatsShell(object):
|
||||
def get_base_parser(self):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='dbstats',
|
||||
add_help=False,
|
||||
formatter_class=HelpFormatter,
|
||||
)
|
||||
parser.add_argument('-h', '--help',
|
||||
action='store_true',
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
parser.add_argument('--clusterlog',
|
||||
help="The syslog file of xcat.",
|
||||
default='/var/log/xcat/cluster.log',
|
||||
type=str)
|
||||
parser.add_argument('--commandlog',
|
||||
help="The command log file of xcat.",
|
||||
default='/var/log/xcat/commands.log',
|
||||
type=str)
|
||||
parser.add_argument('-n', '--num',
|
||||
help="The recent count of commands to analyze",
|
||||
type=int,
|
||||
default=10)
|
||||
parser.add_argument('-c', '--command',
|
||||
help="The specified command to track",
|
||||
type=str,
|
||||
default=None)
|
||||
return parser
|
||||
|
||||
def do_help(self, args):
|
||||
self.parser.print_help()
|
||||
|
||||
def main(self, argv):
|
||||
self.parser = self.get_base_parser()
|
||||
(options, args) = self.parser.parse_known_args(argv)
|
||||
|
||||
if options.help:
|
||||
self.do_help(options)
|
||||
return 0
|
||||
|
||||
a = Analysis(options.commandlog, options.clusterlog)
|
||||
a.process(options.num, options.command)
|
||||
|
||||
|
||||
class HelpFormatter(argparse.HelpFormatter):
|
||||
def start_section(self, heading):
|
||||
# Title-case the headings
|
||||
heading = '%s%s' % (heading[0].upper(), heading[1:])
|
||||
super(HelpFormatter, self).start_section(heading)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
StatsShell().main(sys.argv[1:])
|
@ -14,25 +14,70 @@ use warnings;
|
||||
|
||||
my $program_name = basename("$0");
|
||||
my $help;
|
||||
my $noderange = "compute";
|
||||
my $noderange = undef;
|
||||
my $test;
|
||||
my $output = "stdout";
|
||||
my $verbose = 0;
|
||||
my $rst = 0;
|
||||
my $interval = 5;
|
||||
my $terminal = 0;
|
||||
my $timeout = 0;
|
||||
my $start_time;
|
||||
|
||||
#-----------------------------
|
||||
# To store the node number of a specified type
|
||||
# May like this:
|
||||
# $type_nodesnum{pdu} = 2;
|
||||
# {switch} = 3;
|
||||
# {node} = 10;
|
||||
#-----------------------------
|
||||
my %type_nodesnum = ();
|
||||
|
||||
#-----------------------------
|
||||
# To store the type, state hash
|
||||
# May like this:
|
||||
# $state_node_hash{pdu}{state1}{pdu1} = 1;
|
||||
# $state_node_hash{pdu}{state1}{pdu2} = 1;
|
||||
# $state_node_hash{pdu}{state2}{pdu3} = 1;
|
||||
# $state_node_hash{pdu}{state3}{pdu4} = 1;
|
||||
# The state include but not limited to below:
|
||||
# matching --> matched --> configured (For PDU/Switch)
|
||||
# matching --> matched --> installing --> booting --> booted
|
||||
# matching --> matched --> booting --> installing --> xxx --> booted
|
||||
# The terminal state is configured(For PDU/Switch) or booted(for Node)
|
||||
#-----------------------------
|
||||
my %state_node_hash = ();
|
||||
|
||||
# $state_node_hash{pdu}{state1}{number} = xx;
|
||||
my %state_node_number = ();
|
||||
|
||||
#----------------------------
|
||||
# To store the node based current state
|
||||
# May like this:
|
||||
# $node_info{node1}{state} = "install";
|
||||
# $node_info{node1}{type} = "node";
|
||||
#----------------------------
|
||||
my %node_info = ();
|
||||
|
||||
#---------------------------
|
||||
# To store nodes who haven't finished the status
|
||||
#---------------------------
|
||||
my %unfinished_nodes = ();
|
||||
my %unmatched_nodes = ();
|
||||
|
||||
$::USAGE = "Usage:
|
||||
$program_name -h
|
||||
$program_name {-d|-g} [-n noderange] [-V|--verbose]
|
||||
$program_name [-n noderange] [-V|--verbose] [-i|--interval <seconds>] [--timeout <seconds>]
|
||||
|
||||
Description:
|
||||
Use this command to get a summary of the cluster.
|
||||
|
||||
Options:
|
||||
-h : Get usage information of $program_name
|
||||
-n : Range of nodes to check. Default is \"compute\".
|
||||
-d : Discovery. Display count of discovered nodes.
|
||||
-g : Group count. Display count of nodes in each group.
|
||||
-n : Range of nodes to check. All node objects will be used if not specified.
|
||||
-i : The interval for screen refreshing, unit is second(s), 5 seconds by default.
|
||||
-V : To print additional debug information.
|
||||
--timeout: The timout if not all nodes finish, unit is second(s), no timeout by default.
|
||||
";
|
||||
|
||||
#-------------------------------------
|
||||
@ -44,6 +89,8 @@ if (
|
||||
"V|verbose" => \$VERBOSE,
|
||||
"d|discovery" => \$DISCOVERY,
|
||||
"g|groupcount" => \$GROUPCOUNT,
|
||||
"i|interval=s" => \$interval,
|
||||
"timeout=s" => \$timeout,
|
||||
"n=s" => \$noderange))
|
||||
{
|
||||
probe_utils->send_msg("$output", "f", "Invalid parameter for $program_name");
|
||||
@ -65,12 +112,6 @@ if ($test) {
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ((!$DISCOVERY) and (!$GROUPCOUNT)) {
|
||||
probe_utils->send_msg("$output", "f", "Discovery or groupcount option is required for $program_name");
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if (scalar(@ARGV) >= 1) {
|
||||
|
||||
# After processing all the expected flags and arguments,
|
||||
@ -79,10 +120,42 @@ if (scalar(@ARGV) >= 1) {
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
if (!$DISCOVERY and !$GROUPCOUNT) {
|
||||
if(!defined($noderange)) {
|
||||
$noderange = "all";
|
||||
}
|
||||
} else {
|
||||
if (!defined($noderange)) {
|
||||
$noderange = "compute";
|
||||
}
|
||||
check_for_discovered_nodes() if ($DISCOVERY);
|
||||
groupcount_nodes() if ($GROUPCOUNT);
|
||||
exit 0;
|
||||
}
|
||||
|
||||
check_for_discovered_nodes() if ($DISCOVERY);
|
||||
groupcount_nodes() if ($GROUPCOUNT);
|
||||
$SIG{TERM} = $SIG{INT} = sub {
|
||||
$terminal = 1;
|
||||
};
|
||||
unless ($interval) {
|
||||
$interval = 5;
|
||||
}
|
||||
|
||||
&check_nodes_attributes();
|
||||
$start_time = time;
|
||||
while (1) {
|
||||
update_nodes_info();
|
||||
alarm_output(1);
|
||||
if ($terminal) {
|
||||
alarm_output(0);
|
||||
last;
|
||||
}
|
||||
if ($timeout and (time() - $start_time > $timeout)) {
|
||||
alarm_output(0);
|
||||
last;
|
||||
}
|
||||
sleep $interval;
|
||||
}
|
||||
exit 0;
|
||||
# Check for node definitions with MAC address defined
|
||||
sub check_for_discovered_nodes {
|
||||
my $na = "N/A";
|
||||
@ -132,3 +205,128 @@ sub groupcount_nodes {
|
||||
probe_utils->send_msg("$output", "w", "Group count function is not yet implemented.");
|
||||
return $rc;
|
||||
}
|
||||
|
||||
sub alarm_output {
|
||||
my $flag = shift;
|
||||
if ($flag) {
|
||||
probe_utils->send_msg("$output", "xx", `clear`);
|
||||
my $time_elapsed = time - $start_time;
|
||||
probe_utils->send_msg("$output", "xx", "====".localtime()."($time_elapsed seconds Elapsed)");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "xx", "\nThe cluster state===============================");
|
||||
}
|
||||
foreach my $type (keys(%state_node_hash)) {
|
||||
unless ($type_nodesnum{$type}) {
|
||||
probe_utils->send_msg("$output", "w", "$type Total number: $type_nodesnum{$type}");
|
||||
next;
|
||||
}
|
||||
probe_utils->send_msg("$output", "xx", "$type(Total: $type_nodesnum{$type})--------------------------");
|
||||
foreach my $state (keys(%{$state_node_hash{$type}})) {
|
||||
my $node_number = scalar(keys %{$state_node_hash{$type}{$state}});
|
||||
if ($flag) {
|
||||
my $number = sprintf("%.2f", $node_number * 100.0/ $type_nodesnum{$type});
|
||||
probe_utils->send_msg("$output", "xx", "\t$state : $node_number($number%)");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "xx", "\t$state($node_number): ". join(",",keys %{$state_node_hash{$type}{$state}}) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub update_nodes_info {
|
||||
if (keys(%unmatched_nodes)) {
|
||||
my $unmatched_noderange = join(",", keys(%unmatched_nodes));
|
||||
my @unmatched_nodes_attributes = `lsdef -i mac -c $unmatched_noderange 2> /dev/null`;
|
||||
foreach (@unmatched_nodes_attributes) {
|
||||
if (/^(.*):\s*mac=(.*)$/) {
|
||||
if ($2) {
|
||||
update_node_info($1, "Matched");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keys(%unfinished_nodes)) {
|
||||
my $unfinished_noderange = join(",", keys(%unfinished_nodes));
|
||||
my @unfinished_nodes_attributes = `lsdef -i status -c $unfinished_noderange 2> /dev/null`;
|
||||
foreach (@unfinished_nodes_attributes) {
|
||||
if (/^(.*):\s*status=(.*)$/) {
|
||||
if ($2) {
|
||||
update_node_info($1, "$2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unless(scalar keys(%unfinished_nodes)) {
|
||||
$terminal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub update_node_info {
|
||||
my $node = shift;
|
||||
my $state = shift;
|
||||
my $node_type = $node_info{$node}{type};
|
||||
my $node_state = $node_info{$node}{state};
|
||||
if ($state and $state ne '') {
|
||||
if (exists($unmatched_nodes{$node})) {
|
||||
delete($unmatched_nodes{$node});
|
||||
$unfinished_nodes{$node} = 1;
|
||||
}
|
||||
}
|
||||
if ($state eq $node_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (exists($state_node_hash{$node_type}{$node_state}{$node})) {
|
||||
delete($state_node_hash{$node_type}{$node_state}{$node});
|
||||
}
|
||||
unless (scalar keys ($state_node_hash{$node_type}{$node_state})) {
|
||||
delete($state_node_hash{$node_type}{$node_state});
|
||||
}
|
||||
|
||||
$state_node_hash{$node_type}{$state}{$node} = 1;
|
||||
|
||||
$node_info{$node}{state} = $state;
|
||||
if ($state eq 'booted' or $state eq 'configured') {
|
||||
delete $unfinished_nodes{$node};
|
||||
}
|
||||
}
|
||||
sub check_nodes_attributes {
|
||||
my @nodes_attributes = `lsdef -i status,mac,mgt -c $noderange 2> /dev/null`;
|
||||
my %nodehash = ();
|
||||
foreach (@nodes_attributes) {
|
||||
if (/^(.*):\s*([^=]*)=(.*)$/) {
|
||||
$nodehash{$1}{$2}=$3;
|
||||
}
|
||||
}
|
||||
foreach (keys %nodehash) {
|
||||
if (!defined($nodehash{$_}{mgt})) {
|
||||
probe_utils->send_msg("$output", "w", "No 'mgt' set for node:$_");
|
||||
next;
|
||||
}
|
||||
if ($nodehash{$_}{status}) {
|
||||
$node_info{$_}{state} = $nodehash{$_}{status};
|
||||
$unfinished_nodes{$_} = 1;
|
||||
} elsif ($nodehash{$_}{mac}) {
|
||||
$node_info{$_}{state} = "Matched";
|
||||
$unfinished_nodes{$_} = 1;
|
||||
} else {
|
||||
$node_info{$_}{state} = "matching";
|
||||
$unmatched_nodes{$_} = 1;
|
||||
}
|
||||
if ($nodehash{$_}{mgt} eq 'pdu') {
|
||||
$node_info{$_}{type} = 'pdu';
|
||||
} elsif($nodehash{$_}{mgt} eq 'switch') {
|
||||
$node_info{$_}{type} = 'switch';
|
||||
} else {
|
||||
$node_info{$_}{type} = 'node';
|
||||
}
|
||||
my $node_type = $node_info{$_}{type};
|
||||
if (!exists($type_nodesnum{$node_type})) {
|
||||
$type_nodesnum{$node_type} = 1;
|
||||
} else {
|
||||
$type_nodesnum{$node_type} += 1;
|
||||
}
|
||||
$state_node_hash{$node_type}{$node_info{$_}{state}}{$_} = 1;
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
|
@ -242,12 +242,19 @@ sub check_pre_defined_node {
|
||||
$vpd_line =~ s/"//g;
|
||||
my @split_vpd = split(",", $vpd_line);
|
||||
if (($split_vpd[1] ne "") and ($split_vpd[2] ne "")) {
|
||||
my $mtmsvpd = "$split_vpd[2]*$split_vpd[1]";
|
||||
push @{ $mtms_node{$mtmsvpd} }, $split_vpd[0];
|
||||
my $mtms = uc ("$split_vpd[2]*$split_vpd[1]");
|
||||
my $tmp_node = $split_vpd[0];
|
||||
my $tmp_type = `lsdef $tmp_node -i hwtype,nodetype -c`;
|
||||
if ($tmp_type =~ /hwtype=bmc/ and $tmp_type =~ /nodetype=mp/) {
|
||||
push @{ $mtms_node{$mtms}{bmc} }, $tmp_node;
|
||||
} else {
|
||||
push @{ $mtms_node{$mtms}{node} }, $tmp_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @error_mtms;
|
||||
my @error_mtms_bmc;
|
||||
foreach my $node (keys %nodecheckrst) {
|
||||
|
||||
# check pre-define node whether has mtm and serial
|
||||
@ -259,26 +266,13 @@ sub check_pre_defined_node {
|
||||
|
||||
# check if there is one or more node has the same mtms with current node
|
||||
my $mtms = "$nodecheckrst{$node}{\"mtm\"}*$nodecheckrst{$node}{\"serial\"}";
|
||||
my $mtms_num = @{$mtms_node{$mtms}};
|
||||
if ($mtms_num > 2) {
|
||||
my $mtms_node_num = @{ $mtms_node{$mtms}{node} };
|
||||
my $mtms_bmc_num = @{ $mtms_node{$mtms}{bmc} };
|
||||
if ($mtms_node_num >= 2) {
|
||||
push @error_mtms, $mtms if (!grep {$_ eq $mtms} @error_mtms);
|
||||
} elsif ($mtms_num == 2) {
|
||||
foreach my $mtmsnode (@{$mtms_node{$mtms}}) {
|
||||
next if ($mtmsnode eq $node);
|
||||
if (exists($nodecheckrst{$mtmsnode})) {
|
||||
if (($nodecheckrst{$mtmsnode}{"nodetype"} eq $nodecheckrst{$node}{"nodetype"}) and ($nodecheckrst{$mtmsnode}{"hwtype"} eq $nodecheckrst{$node}{"hwtype"})) {
|
||||
push @error_mtms, $mtms if (!grep {$_ eq $mtms} @error_mtms);
|
||||
}
|
||||
} else {
|
||||
my $nodetype = `lsdef $mtmsnode -i nodetype -c |awk -F"=" '{print \$2}'`;
|
||||
my $hwtype = `lsdef $mtmsnode -i hwtype -c |awk -F"=" '{print \$2}'`;
|
||||
chomp($nodetype);
|
||||
chomp($hwtype);
|
||||
if (($nodetype eq $nodecheckrst{$node}{"nodetype"}) and ($hwtype eq $nodecheckrst{$node}{"hwtype"})) {
|
||||
push @error_mtms, $mtms if (!grep {$_ eq $mtms} @error_mtms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($mtms_bmc_num >= 2) {
|
||||
push @error_mtms_bmc, $mtms if (!grep {$_ eq $mtms} @error_mtms_bmc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,11 +285,20 @@ sub check_pre_defined_node {
|
||||
|
||||
if (@error_mtms) {
|
||||
foreach (@error_mtms) {
|
||||
my $errornode = join(",", @{$mtms_node{$_}});
|
||||
my $errornode = join(",", @{$mtms_node{$_}{node}});
|
||||
probe_utils->send_msg("stdout", "f", "[$errornode] : Duplicate node definition found for the same mtms $_.");
|
||||
$rst = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (@error_mtms_bmc) {
|
||||
foreach (@error_mtms_bmc) {
|
||||
my $errorbmcnode = join(",", @{$mtms_node{$_}{bmc}});
|
||||
my $errornode = join(",", @{$mtms_node{$_}{node}});
|
||||
probe_utils->send_msg("stdout", "f", "[$errornode] : Duplicate BMC node ($errorbmcnode) definition found for the same mtms $_.");
|
||||
$rst = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($discovery_type eq "switch") {
|
||||
@ -356,7 +359,7 @@ sub check_pre_defined_node {
|
||||
next;
|
||||
}
|
||||
|
||||
if (!(exists($nodecheckrst{$node}{"switchport"})) or $nodecheckrst{$node}{"switchport"} !~ /^\w/ or $valid_nodes !~ $node) {
|
||||
if (!(exists($nodecheckrst{$node}{"switchport"})) or $nodecheckrst{$node}{"switchport"} !~ /^\d+$/ or $valid_nodes !~ $node) {
|
||||
push @error_attribute, "switchport";
|
||||
}
|
||||
|
||||
@ -378,18 +381,6 @@ sub check_pre_defined_node {
|
||||
$keystring = "Missing definition for related switch $nodecheckrst{$node}{\"switch\"}";
|
||||
last;
|
||||
}
|
||||
if ($tmpoutput !~ /snmpversion=/) {
|
||||
$keystring = "Missing attribute 'snmpversion' definition for related switch $nodecheckrst{$node}{\"switch\"}";
|
||||
last;
|
||||
}
|
||||
if ($tmpoutput !~ /username=/) {
|
||||
$keystring = "Missing attribute 'username' definition for related switch $nodecheckrst{$node}{\"switch\"}";
|
||||
last;
|
||||
}
|
||||
if ($tmpoutput !~ /password=/) {
|
||||
$keystring = "Missing attribute 'password' definition for related switch $nodecheckrst{$node}{\"switch\"}";
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($keystring) {
|
||||
@ -533,7 +524,6 @@ sub check_genesis_file {
|
||||
my $rst = 0;
|
||||
my @warn_msg;
|
||||
|
||||
my $genesis_v;
|
||||
my $os = probe_utils->get_os();
|
||||
if ($os =~ "unknown") {
|
||||
probe_utils->send_msg("stdout", "f", $msg);
|
||||
@ -549,7 +539,6 @@ sub check_genesis_file {
|
||||
probe_utils->send_msg("stdout", "d", "xCAT-genesis is not installed.");
|
||||
return 1;
|
||||
}
|
||||
$genesis_v = `dpkg -s xcat-genesis-base-ppc64`;
|
||||
} else {
|
||||
my $genesis_output = `rpm -qa | grep -i "xcat-genesis"`;
|
||||
unless (($genesis_output =~ /base/ and $genesis_output =~ /ppc64/) and
|
||||
@ -560,15 +549,6 @@ sub check_genesis_file {
|
||||
probe_utils->send_msg("stdout", "d", "xCAT-genesis is not installed.");
|
||||
return 1;
|
||||
}
|
||||
$genesis_v = `rpm -qi xCAT-genesis-base-ppc64`;
|
||||
}
|
||||
|
||||
if ($genesis_v =~ /Built in environment .+fc(\d*).+ on (.+)\./) {
|
||||
my $ver = $1;
|
||||
my $arch = $2;
|
||||
push @warn_msg, "xcat-genesis-base-ppc64 is not built in environment fedora 26 or higher version on $arch." if ($ver < 26);
|
||||
} else {
|
||||
push @warn_msg, "xcat-genesis-base-ppc64 is not built in environment fedora.";
|
||||
}
|
||||
|
||||
my $genesis_update_flag_p;
|
||||
@ -649,14 +629,13 @@ sub check_genesis_file {
|
||||
$rst = 1;
|
||||
}
|
||||
|
||||
if ($initrd_path =~ /http.+($tftpdir\/.+)/) {
|
||||
if ($initrd_path =~ /http:\/\/.+:80(\/.+)/) {
|
||||
my $initrd_file = $1;
|
||||
my $initrd_time = `stat $initrd_file | grep Modify | cut -d ' ' -f 2-3`;
|
||||
if ($genesis_time and $initrd_time < $genesis_time) {
|
||||
$genesis_update_flag_p = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($genesis_line =~ /^kernel/) {
|
||||
|
@ -92,10 +92,10 @@ sub check_for_duplicate_mtms_sn {
|
||||
chomp($all_nodes_mtm_serial);
|
||||
my @all_nodes_mtm_serial_lines = split("[\n\r]", $all_nodes_mtm_serial);
|
||||
|
||||
if ($all_nodes_mtm_serial =~ /Usage:/) {
|
||||
if ($all_nodes_mtm_serial =~ /Usage:|Could not find any object definitions to display/) {
|
||||
|
||||
# lsdef command displayed a Usage message. Must be some noderange formatting problem.
|
||||
# Issue a warning and exit.
|
||||
# lsdef command displayed a Usage message. Must be some noderange formatting problem,
|
||||
# or no nodes defined at all. Issue a warning and exit.
|
||||
probe_utils->send_msg("$output", "w", "Can not get a list of nodes from specified noderange.");
|
||||
return 1;
|
||||
}
|
||||
|
@ -120,6 +120,7 @@ foreach (<$fd>) {
|
||||
}
|
||||
}
|
||||
close($fd);
|
||||
my $rc = 0;
|
||||
if (-f $normal_file) {
|
||||
unlink($normal_file);
|
||||
}
|
||||
@ -129,8 +130,10 @@ if (-f $error_file) {
|
||||
if (@error_nodes) {
|
||||
my $error_node = join(",", @error_nodes);
|
||||
probe_utils->send_msg("$output", "d", "[$error_node] : Error, switch-macmap can only be run against xCAT objects that have 'nodetype=switch'");
|
||||
$rc = 1;
|
||||
}
|
||||
foreach (@fails) {
|
||||
probe_utils->send_msg("$output", "f", "$_");
|
||||
$rc = 1;
|
||||
}
|
||||
exit 0;
|
||||
exit $rc;
|
||||
|
@ -44,6 +44,7 @@ mkdir -p $RPM_BUILD_ROOT/%{prefix}/probe/
|
||||
cp xcatprobe $RPM_BUILD_ROOT/%{prefix}/bin
|
||||
cp -r subcmds $RPM_BUILD_ROOT/%{prefix}/probe/
|
||||
cp -r lib $RPM_BUILD_ROOT/%{prefix}/probe/
|
||||
cp -r scripts $RPM_BUILD_ROOT/%{prefix}/probe/
|
||||
|
||||
%clean
|
||||
# This step does not happen until *after* the %files packaging below
|
||||
|
@ -82,9 +82,9 @@ sub subvars {
|
||||
close($inh);
|
||||
|
||||
#the logic to determine the $ENV{XCATMASTER} confirm to the following priority(from high to low):
|
||||
#the "xcatmaster" attribute of the node
|
||||
#the site.master
|
||||
#the ip address of the mn facing the compute node
|
||||
## 1, the "xcatmaster" attribute of the node
|
||||
## 2, the ip address of the mn/sn facing the compute node
|
||||
## 3, the site.master
|
||||
my $master;
|
||||
|
||||
#the "xcatmaster" attribute of the node
|
||||
@ -94,16 +94,6 @@ sub subvars {
|
||||
$master = $et->{'xcatmaster'};
|
||||
}
|
||||
|
||||
unless ($master) {
|
||||
|
||||
#the site.master
|
||||
my @masters = xCAT::TableUtils->get_site_attribute("master");
|
||||
my $tmp = $masters[0];
|
||||
if (defined($tmp)) {
|
||||
$master = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($master) {
|
||||
|
||||
#the ip address of the mn facing the compute node
|
||||
@ -115,14 +105,23 @@ sub subvars {
|
||||
}
|
||||
}
|
||||
|
||||
unless ($master) {
|
||||
|
||||
#the site.master
|
||||
my @masters = xCAT::TableUtils->get_site_attribute("master");
|
||||
my $tmp = $masters[0];
|
||||
if (defined($tmp)) {
|
||||
$master = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($master) {
|
||||
$tmplerr = "Unable to identify master for $node";
|
||||
return;
|
||||
}
|
||||
|
||||
$ENV{XCATMASTER} = $master;
|
||||
|
||||
my ($host, $ipaddr) = xCAT::NetworkUtils->gethostnameandip($master);
|
||||
my $ipaddr = xCAT::NetworkUtils->getipaddr($master);
|
||||
if ($ipaddr) {
|
||||
$ENV{MASTER_IP} = "$ipaddr";
|
||||
}
|
||||
|
@ -1693,7 +1693,6 @@ sub defmk
|
||||
{
|
||||
|
||||
my $type = $::FINALATTRS{$obj}{objtype};
|
||||
|
||||
# check to make sure we have type
|
||||
if (!$type)
|
||||
{
|
||||
@ -1714,10 +1713,30 @@ sub defmk
|
||||
my @nets = xCAT::DBobjUtils->getObjectsOfType('network');
|
||||
my %objhash;
|
||||
foreach my $n (@nets) {
|
||||
# netname is duplicate
|
||||
if ( $obj eq $n ) {
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "A network definition called \'$n\' already exists. Cannot create a definition for \'$obj\'.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::callback);
|
||||
$error = 1;
|
||||
delete $::FINALATTRS{$obj};
|
||||
next OBJ;
|
||||
}
|
||||
$objhash{$n} = $type;
|
||||
}
|
||||
# When adding a new network entry, net and mask cannot be empty
|
||||
if (!($::FINALATTRS{$obj}{net} && $::FINALATTRS{$obj}{mask}))
|
||||
{
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "Net or mask value should not be empty for xCAT network object \'$obj\'.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::callback);
|
||||
$error = 1;
|
||||
delete $::FINALATTRS{$obj};
|
||||
next OBJ;
|
||||
}
|
||||
my %nethash = xCAT::DBobjUtils->getobjdefs(\%objhash);
|
||||
foreach my $o (keys %nethash) {
|
||||
# there is a network entry contains the same net and mask
|
||||
if (($nethash{$o}{net} eq $::FINALATTRS{$obj}{net}) && ($nethash{$o}{mask} eq $::FINALATTRS{$obj}{mask})) {
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "A network definition called \'$o\' already exists that contains the same net and mask values. Cannot create a definition for \'$obj\'.";
|
||||
@ -1727,6 +1746,7 @@ sub defmk
|
||||
next OBJ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# if object already exists
|
||||
@ -2370,6 +2390,74 @@ sub defch
|
||||
$isDefined = 1;
|
||||
}
|
||||
|
||||
if ($type eq 'network')
|
||||
{
|
||||
my $isInvalid = 0;
|
||||
# When adding a new network entry, net and mask cannot be empty
|
||||
if (!$isDefined && !($::FINALATTRS{$obj}{'net'} && $::FINALATTRS{$obj}{'mask'}))
|
||||
{
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "Net or mask value should not be empty for xCAT network object \'$obj\'.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::callback);
|
||||
$error = 1;
|
||||
$isInvalid = 1;
|
||||
delete($::FINALATTRS{$obj});
|
||||
next;
|
||||
}
|
||||
my @nets = xCAT::DBobjUtils->getObjectsOfType('network');
|
||||
my %objhash;
|
||||
foreach my $n (@nets) {
|
||||
$objhash{$n} = $type;
|
||||
}
|
||||
# get original networks data
|
||||
my %nethash = xCAT::DBobjUtils->getobjdefs(\%objhash);
|
||||
foreach my $o (keys %nethash) {
|
||||
# the netname already exists
|
||||
if ($isDefined)
|
||||
{
|
||||
# when net is empty, chdef command should add net value, $::FINALATTRS{$obj}{net} should have value
|
||||
if ((!$nethash{$o}{net}) && (!$::FINALATTRS{$obj}{net}))
|
||||
{
|
||||
$isInvalid=1;
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "Attribute \'net\' is not specified for network entry \'$obj\', skipping.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::callback);
|
||||
$error = 1;
|
||||
last;
|
||||
}
|
||||
# when mask is empty, chdef command should add mask value, $::FINALATTRS{$obj}{mask} should have value
|
||||
if ((!$nethash{$o}{mask}) && (!$::FINALATTRS{$obj}{mask}))
|
||||
{
|
||||
$isInvalid=1;
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "Attribute \'mask\' is not specified for network entry \'$obj\', skipping.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::callback);
|
||||
$error = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
# the netname does not exist
|
||||
else {
|
||||
# there is a network definition already contains the same net and mask, it is duplicate
|
||||
if (($nethash{$o}{net} eq $::FINALATTRS{$obj}{net}) && ($nethash{$o}{mask} eq $::FINALATTRS{$obj}{mask}))
|
||||
{
|
||||
$isInvalid=1;
|
||||
my $rsp;
|
||||
$rsp->{data}->[0] = "A network definition called \'$o\' already exists that contains the same net and mask values. Cannot create a definition for \'$obj\'.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $::callback);
|
||||
$error = 1;
|
||||
last;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if($isInvalid)
|
||||
{
|
||||
delete($::FINALATTRS{$obj});
|
||||
next;
|
||||
}
|
||||
}
|
||||
if (!$isDefined && ($type eq 'node') && (!defined($::FINALATTRS{$obj}{'groups'}) || !$::FINALATTRS{$obj}{'groups'}))
|
||||
{
|
||||
my $rsp;
|
||||
|
@ -28,21 +28,6 @@ sub process_request {
|
||||
}
|
||||
my $client_ip = $req->{'_xcat_clientip'};
|
||||
|
||||
#now, notify the node that its findme request is under processing
|
||||
xCAT::MsgUtils->message("S", "Notify $client_ip that its findme request is processing\n");
|
||||
my $sock = new IO::Socket::INET(
|
||||
PeerAddr => $client_ip,
|
||||
PeerPort => '3001',
|
||||
Timeout => '1',
|
||||
Proto => 'tcp'
|
||||
);
|
||||
if ($sock) {
|
||||
print $sock "processing";
|
||||
close($sock);
|
||||
}else{
|
||||
xCAT::MsgUtils->message("S", "Failed to notify $client_ip that its findme request is processing.");
|
||||
}
|
||||
|
||||
my $arptable;
|
||||
if (-x "/usr/sbin/arp") {
|
||||
$arptable = `/usr/sbin/arp -n`;
|
||||
|
@ -141,16 +141,16 @@ sub process_request {
|
||||
$clipassword = $password;
|
||||
}
|
||||
unless (defined $bmc) {
|
||||
xCAT::MsgUtils->message('S', "Received request from host=$node but unable to determine $bmc_mgmt_type.bmc value for the node. Verify mgt attribute is configured correctly for the node and the BMC is defined.");
|
||||
$callback->({ error => ["Unable to detect BMC configuration value for bmcconfig"], errorcode => [1] });
|
||||
xCAT::MsgUtils->message('S', "Received request from host=$node but unable to determine the $bmc_mgmt_type.bmc value for the node. Verify the node.mgt attribute is configured and the node.bmc is defined.");
|
||||
$callback->({ error => ["No value specified for '$node.bmc'. Unable to configure the BMC, check the node definition."], errorcode => [1] });
|
||||
return 1;
|
||||
}
|
||||
my $bmcport_counter = 0;
|
||||
foreach my $sbmc (split /,/, $bmc) {
|
||||
(my $ip, my $mask, my $gw) = net_parms($sbmc);
|
||||
unless ($ip and $mask and $username and $password) {
|
||||
xCAT::MsgUtils->message('S', "Unable to determine IP, netmask, username, and/or pasword for $sbmc, ensure that host resolution is working. Best guess parameters would have been: IP: '$ip', netmask: '$mask', username: '$username', password: '$password'",);
|
||||
$callback->({ error => ["Invalid table configuration for bmcconfig"], errorcode => [1] });
|
||||
xCAT::MsgUtils->message('S', "Unable to determine IP, Netmask, Username, or Password for $sbmc. Ensure that hostname resolution is working. [IP=$ip Netmask=$mask User=$username Pass=$password]",);
|
||||
$callback->({ error => ["Invalid/Missing BMC related attributes in the node defintion (IP=$ip Netmask=$mask User=$username Pass=$password). Unable to configure the BMC, check the node definition."], errorcode => [1] });
|
||||
return 1;
|
||||
}
|
||||
if ($request->{command}->[0] eq 'remoteimmsetup') {
|
||||
|
@ -125,14 +125,6 @@ sub process_request
|
||||
my $request_command = shift;
|
||||
$::CALLBACK = $callback;
|
||||
|
||||
#$::args = $request->{arg};
|
||||
if (ref($request->{environment}) eq 'ARRAY' and ref($request->{environment}->[0]->{XCAT_DEV_WITHERSPOON}) eq 'ARRAY') {
|
||||
$::XCAT_DEV_WITHERSPOON = $request->{environment}->[0]->{XCAT_DEV_WITHERSPOON}->[0];
|
||||
} elsif (ref($request->{environment}) eq 'ARRAY') {
|
||||
$::XCAT_DEV_WITHERSPOON = $request->{environment}->[0]->{XCAT_DEV_WITHERSPOON};
|
||||
} else {
|
||||
$::XCAT_DEV_WITHERSPOON = $request->{environment}->{XCAT_DEV_WITHERSPOON};
|
||||
}
|
||||
if ($request->{sn}) {
|
||||
my $dhcpservers = $request->{dhcpservers};
|
||||
if (!defined($dhcpservers) or ref($dhcpservers) ne 'ARRAY') {
|
||||
@ -191,7 +183,7 @@ sub bmcdiscovery_usage {
|
||||
push @{ $rsp->{data} }, "Usage:";
|
||||
push @{ $rsp->{data} }, "\tbmcdiscover [-?|-h|--help]";
|
||||
push @{ $rsp->{data} }, "\tbmcdiscover [-v|--version]";
|
||||
push @{ $rsp->{data} }, "\tbmcdiscover [-s scan_method] [-u bmc_user] [-p bmc_passwd] [-z] [-w] --range ip_range\n";
|
||||
push @{ $rsp->{data} }, "\tbmcdiscover [--sn <SN_nodename>] [-s scan_method] [-u bmc_user] [-p bmc_passwd] [-z] [-w] --range ip_range\n";
|
||||
|
||||
push @{ $rsp->{data} }, "\tCheck BMC administrator User/Password:\n";
|
||||
push @{ $rsp->{data} }, "\t\tbmcdiscover -u bmc_user -p bmc_password -i bmc_ip --check\n";
|
||||
@ -566,7 +558,7 @@ sub scan_process {
|
||||
my $children; # The number of child process
|
||||
my %sp_children; # Record the pid of child process
|
||||
my $bcmd;
|
||||
my $sub_fds = new IO::Select; # Record the parent fd for each child process
|
||||
|
||||
|
||||
if (!defined($method))
|
||||
{
|
||||
@ -617,7 +609,7 @@ sub scan_process {
|
||||
|
||||
my $live_ip = split_comma_delim_str($ip_list);
|
||||
my $live_mac = split_comma_delim_str($mac_list);
|
||||
|
||||
my %pipe_map;
|
||||
if (scalar(@{$live_ip}) > 0) {
|
||||
|
||||
foreach (@{$live_ip}) {
|
||||
@ -651,6 +643,9 @@ sub scan_process {
|
||||
if ($sp_children{$cpid}) {
|
||||
delete $sp_children{$cpid};
|
||||
$children--;
|
||||
forward_data($callback, $pipe_map{$cpid});
|
||||
close($pipe_map{$cpid});
|
||||
delete $pipe_map{$cpid};
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -680,7 +675,7 @@ sub scan_process {
|
||||
} else {
|
||||
bmcdiscovery_ipmi(${$live_ip}[$i], $opz, $opw, $request_command);
|
||||
}
|
||||
|
||||
close($parent_fd);
|
||||
exit 0;
|
||||
} else {
|
||||
|
||||
@ -688,23 +683,15 @@ sub scan_process {
|
||||
# the main process will check all the parent fd and receive response
|
||||
$sp_children{$child} = 1;
|
||||
close($parent_fd);
|
||||
$sub_fds->add($cfd);
|
||||
$pipe_map{$child} = $cfd;
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
while ($children >= 32) {
|
||||
sleep(1);
|
||||
} until ($children < 32);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#################################################
|
||||
# receive data from child processes
|
||||
################################################
|
||||
while ($sub_fds->count > 0 or $children > 0) {
|
||||
forward_data($callback, $sub_fds);
|
||||
}
|
||||
while (forward_data($callback, $sub_fds)) {
|
||||
while($children > 0) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -832,26 +819,14 @@ sub send_rep {
|
||||
|
||||
sub forward_data {
|
||||
my $callback = shift;
|
||||
my $fds = shift;
|
||||
my @ready_fds = $fds->can_read(1);
|
||||
my $rfh;
|
||||
my $rc = @ready_fds;
|
||||
foreach $rfh (@ready_fds) {
|
||||
my $data;
|
||||
my $responses;
|
||||
eval {
|
||||
$responses = fd_retrieve($rfh);
|
||||
};
|
||||
if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
|
||||
$fds->remove($rfh);
|
||||
close($rfh);
|
||||
} else {
|
||||
eval { print $rfh "ACK\n"; }; #Ignore ack loss due to child giving up and exiting, we don't actually explicitly care about the acks
|
||||
$callback->($responses);
|
||||
}
|
||||
my $cfd = shift;
|
||||
my $responses;
|
||||
eval {
|
||||
$responses = fd_retrieve($cfd);
|
||||
};
|
||||
if (!($@ and $@ =~ /^Magic number checking on storable file/)) { #this most likely means we ran over the end of available input
|
||||
$callback->($responses);
|
||||
}
|
||||
yield; #Try to avoid useless iterations as much as possible
|
||||
return $rc;
|
||||
}
|
||||
|
||||
|
||||
@ -1107,19 +1082,8 @@ sub bmcdiscovery_ipmi {
|
||||
xCAT::MsgUtils->message("W", { data => ["BMC password is incorrect for $ip"] }, $::CALLBACK);
|
||||
return;
|
||||
}
|
||||
if (defined($opz) || defined($opw))
|
||||
{
|
||||
format_stanza($node, $node_data, "ipmi");
|
||||
if (defined($opw))
|
||||
{
|
||||
write_to_xcatdb($node, $node_data, "ipmi", $request_command);
|
||||
}
|
||||
}
|
||||
else {
|
||||
my $rsp = {};
|
||||
push @{ $rsp->{data} }, "$node_data";
|
||||
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
}
|
||||
|
||||
display_output($opz,$opw,$node,$node_data,"ipmi",$request_command);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1180,12 +1144,8 @@ sub bmcdiscovery_openbmc{
|
||||
my $serial;
|
||||
|
||||
if (defined($response->{data})) {
|
||||
if (defined($response->{data}->{PartNumber}) and defined($response->{data}->{SerialNumber})) {
|
||||
$mtm = $response->{data}->{PartNumber};
|
||||
if (defined($::XCAT_DEV_WITHERSPOON) && ($::XCAT_DEV_WITHERSPOON eq "TRUE")) {
|
||||
xCAT::MsgUtils->message("I", { data => ["XCAT_DEV_WITHERSPOON=TRUE, forcing MTM to empty string for $ip (Original MTM=$mtm)"] }, $::CALLBACK);
|
||||
$mtm = "";
|
||||
}
|
||||
if (defined($response->{data}->{Model}) and defined($response->{data}->{SerialNumber})) {
|
||||
$mtm = $response->{data}->{Model};
|
||||
$serial = $response->{data}->{SerialNumber};
|
||||
}
|
||||
|
||||
@ -1195,8 +1155,8 @@ sub bmcdiscovery_openbmc{
|
||||
}
|
||||
|
||||
# delete space before and after
|
||||
$mtm =~ s/^\s+|\s+$//g;
|
||||
$serial =~ s/^\s+|\s+$//g;
|
||||
$mtm =~ s/^\s+|\s+$|\.+//g;
|
||||
$serial =~ s/^\s+|\s+$|\.+//g;
|
||||
|
||||
$mtm = '' if ($mtm =~ /^0+$/);
|
||||
$serial = '' if ($serial =~ /^0+$/);
|
||||
@ -1234,12 +1194,38 @@ sub bmcdiscovery_openbmc{
|
||||
}
|
||||
return;
|
||||
}
|
||||
display_output($opz,$opw,$node,$node_data,"openbmc",$request_command);
|
||||
}
|
||||
|
||||
if (defined($opz) || defined($opw)) {
|
||||
format_stanza($node, $node_data, "openbmc");
|
||||
if (defined($opw)) {
|
||||
write_to_xcatdb($node, $node_data, "openbmc", $request_command);
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
=head3 display_output
|
||||
|
||||
Common code to print output of bmcdiscover
|
||||
|
||||
=cut
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
sub display_output {
|
||||
my $opz = shift;
|
||||
my $opw = shift;
|
||||
my $node = shift;
|
||||
my $node_data = shift;
|
||||
my $mgttype = shift;
|
||||
my $request_command = shift;
|
||||
|
||||
if (defined($opw)) {
|
||||
my $rsp = {};
|
||||
push @{ $rsp->{data} }, "Writing $node ($node_data) to database...";
|
||||
xCAT::MsgUtils->message("I", $rsp, $::CALLBACK);
|
||||
if (defined($opz)) {
|
||||
format_stanza($node, $node_data, $mgttype);
|
||||
}
|
||||
write_to_xcatdb($node, $node_data, $mgttype, $request_command);
|
||||
}
|
||||
elsif (defined($opz)) {
|
||||
format_stanza($node, $node_data, $mgttype);
|
||||
} else {
|
||||
my $rsp = {};
|
||||
push @{ $rsp->{data} }, "$node_data";
|
||||
|
@ -957,6 +957,8 @@ sub mknetboot
|
||||
my $xcatdport = "3001";
|
||||
my $xcatiport = "3002";
|
||||
my $nodestatus = "y";
|
||||
my @myself = xCAT::NetworkUtils->determinehostname();
|
||||
my $myname = $myself[ (scalar @myself) - 1 ];
|
||||
|
||||
if ($sitetab)
|
||||
{
|
||||
@ -1170,7 +1172,7 @@ sub mknetboot
|
||||
if ($statelite) {
|
||||
unless (-r "$rootimgdir/kernel") {
|
||||
$callback->({
|
||||
error => [qq{Did you run "genimage" before running "liteimg"? kernel cannot be found...}],
|
||||
error => [qq{Did you run "genimage" before running "liteimg"? kernel cannot be found at $rootimgdir/kernel on $myname}],
|
||||
errorcode => [1]
|
||||
});
|
||||
next;
|
||||
@ -1197,7 +1199,7 @@ sub mknetboot
|
||||
} else {
|
||||
unless (-r "$rootimgdir/kernel") {
|
||||
$callback->({
|
||||
error => [qq{Did you run "genimage" before running "packimage"? kernel cannot be found}],
|
||||
error => [qq{Did you run "genimage" before running "packimage"? kernel cannot be found at $rootimgdir/kernel on $myname}],
|
||||
errorcode => [1]
|
||||
});
|
||||
next;
|
||||
|
@ -655,8 +655,8 @@ sub setdestiny {
|
||||
if ($reststates) {
|
||||
$updates->{$_}->{'currchain'} = $reststates;
|
||||
}
|
||||
$chaintab->setNodesAttribs($updates);
|
||||
}
|
||||
$chaintab->setNodesAttribs($updates);
|
||||
return getdestiny($flag + 1);
|
||||
}
|
||||
|
||||
@ -784,6 +784,7 @@ sub getdestiny {
|
||||
@nodes = ($node);
|
||||
}
|
||||
my $node;
|
||||
xCAT::MsgUtils->trace(0, "d", "destiny->process_request: getdestiny...");
|
||||
$restab = xCAT::Table->new('noderes');
|
||||
my $chaintab = xCAT::Table->new('chain');
|
||||
my $chainents = $chaintab->getNodesAttribs(\@nodes, [qw(currstate chain)]);
|
||||
|
@ -1128,7 +1128,7 @@ sub preprocess_request
|
||||
$callback->({ error => [ "Hierarchy requested, therefore networks.dhcpserver must be set for net=" . $_->{net} . "" ], errorcode => [1] });
|
||||
return [];
|
||||
}
|
||||
push @dhcpsvrs, $_->{dhcpserver};
|
||||
push @dhcpsvrs, $_->{dhcpserver} if (xCAT::NetworkUtils->nodeonmynet($_->{dhcpserver}));
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "dhcp: dhcp server on $_->{net}: $_->{dhcpserver}");
|
||||
}
|
||||
}
|
||||
|
@ -504,8 +504,7 @@ sub preprocess_request {
|
||||
if ($ntab) {
|
||||
foreach (@{ $ntab->getAllEntries() }) {
|
||||
next unless ($_->{dynamicrange});
|
||||
# if dynamicrange specified but dhcpserver was not - issue error message
|
||||
push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver})
|
||||
push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver} && xCAT::NetworkUtils->nodeonmynet($_->{dhcpserver}));
|
||||
}
|
||||
}
|
||||
return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash, \@dhcpsvrs);
|
||||
@ -816,7 +815,7 @@ sub process_request {
|
||||
if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: issue makedhcp request");
|
||||
$sub_req->({ command => ['makedhcp'],
|
||||
node => \@{ $osimagenodehash{$osimage} } }, $callback);
|
||||
node => \@{ $osimagenodehash{$osimage} }, arg => ['-l'] }, $callback);
|
||||
} else {
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "grub2: issue makedhcp request");
|
||||
$sub_req->({ command => ['makedhcp'],
|
||||
@ -854,7 +853,11 @@ sub process_request {
|
||||
push(@rmdhcp_nodes, $tmp_node);
|
||||
}
|
||||
}
|
||||
$sub_req->({ command => ['makedhcp'], arg => ['-d'], node => \@rmdhcp_nodes }, $callback);
|
||||
if ($request->{'_disparatetftp'}->[0]) {
|
||||
$sub_req->({ command => ['makedhcp'], arg => ['-d', '-l'], node => \@rmdhcp_nodes }, $callback);
|
||||
} else {
|
||||
$sub_req->({ command => ['makedhcp'], arg => ['-d'], node => \@rmdhcp_nodes }, $callback);
|
||||
}
|
||||
}
|
||||
|
||||
#now run the end part of the prescripts
|
||||
|
@ -165,7 +165,7 @@ sub build_line
|
||||
$longname = "$node.$domain";
|
||||
}
|
||||
|
||||
# if shortname contains a dot then we have a bad syntax for name
|
||||
# if shortname contains a dot then we have a bad syntax for name
|
||||
if ($shortname =~ /\./) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Invalid short node name \'$shortname\'. The short node name may not contain a dot. The short node name is considered to be anything preceeding the network domain name in the fully qualified node name \'$longname\'.\n";
|
||||
@ -729,9 +729,28 @@ sub donics
|
||||
for (my $i = 0 ; $i < $nicindex{$nic} ; $i++) {
|
||||
if (!$nich->{$nic}->{nicsufx}->[$i] && !$nich->{$nic}->{nicprfx}->[$i]) {
|
||||
|
||||
if ($nic =~ /\./) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "$node: since \'$nic\' contains dot, nics.nichostnamesuffixes.$nic should be configured without dot for \'$nic\' interface.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
next;
|
||||
}
|
||||
# then we have no suffix at all for this
|
||||
# so set a default
|
||||
$nich->{$nic}->{nicsufx}->[$i] = "-$nic";
|
||||
|
||||
} elsif ($nich->{$nic}->{nicsufx}->[$i] && $nich->{$nic}->{nicsufx}->[$i] =~ /\./) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "$node: the value \'$nich->{$nic}->{nicsufx}->[$i]\' of nics.nichostnamesuffixes.$nic should not contain dot.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
delete $nich->{$nic}->{nicsufx}->[$i];
|
||||
next;
|
||||
} elsif ($nich->{$nic}->{nicprfx}->[$i] && $nich->{$nic}->{nicprfx}->[$i] =~ /\./) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "$node: the value \'$nich->{$nic}->{nicprfx}->[$i]\' of nics.nichostnameprefixes.$nic should not contain dot.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
delete $nich->{$nic}->{nicprfx}->[$i];
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use xCAT_monitoring::monitorctrl;
|
||||
use xCAT::SPD qw/decode_spd/;
|
||||
use xCAT::IPMI;
|
||||
use xCAT::PasswordUtils;
|
||||
use File::Basename;
|
||||
my %needbladeinv;
|
||||
|
||||
use POSIX qw(ceil floor);
|
||||
@ -33,6 +34,7 @@ use xCAT::SvrUtils;
|
||||
use xCAT::NetworkUtils;
|
||||
use xCAT::Usage;
|
||||
use File::Path;
|
||||
use File::Spec;
|
||||
|
||||
use Thread qw(yield);
|
||||
use LWP 5.64;
|
||||
@ -1612,8 +1614,8 @@ sub isopenpower {
|
||||
if ($sessdata->{prod_id} == 43707 and $sessdata->{mfg_id} == 0) {
|
||||
# mft_id 0 and prod_id 43707 is for Firestone,Minsky
|
||||
return 1;
|
||||
} elsif (($sessdata->{prod_id} == 0 or $sessdata->{prod_id} == 2355) and $sessdata->{mfg_id} == 10876) {
|
||||
# mfg_id 10876 is for IBM Power S822LC for Big Data (Supermicro), prod_id 2355 for B&S, and 0 for Boston
|
||||
} elsif (($sessdata->{prod_id} =~ /0|2355|2437/) and $sessdata->{mfg_id} == 10876) {
|
||||
# mfg_id 10876 is for IBM Power S822LC for Big Data (Supermicro), prod_id 2355 for B&S, and 0 or 2437 for Boston
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@ -1929,6 +1931,13 @@ sub do_firmware_update {
|
||||
$buffer_size = "15000";
|
||||
}
|
||||
|
||||
my $directory_name;
|
||||
if (@{ $sessdata->{extraargs} } > 1) {
|
||||
@ARGV = @{ $sessdata->{extraargs} };
|
||||
use Getopt::Long;
|
||||
GetOptions('d:s' => \$directory_name);
|
||||
}
|
||||
|
||||
# check verbose, buffersize, and retry options
|
||||
for my $opt (@{$sessdata->{'extraargs'}}) {
|
||||
if ($opt =~ /-V{1,4}/) {
|
||||
@ -1961,40 +1970,40 @@ sub do_firmware_update {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($opt =~ /-d=/) {
|
||||
my ($attribute, $directory_name) = split(/=/, $opt);
|
||||
if (defined $directory_name) {
|
||||
# directory was passed in, verify it is valid
|
||||
if (-d $directory_name) {
|
||||
# Passed in directory name exists
|
||||
$pUpdate_directory = $directory_name;
|
||||
}
|
||||
else {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback,
|
||||
"Can not access data directory $directory_name");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback,
|
||||
"Data directory must be specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# For IBM Power S822LC for Big Data (Supermicro) machines such as P9 Boston (9006-22C) or P8 Briggs (8001-22C)
|
||||
# For IBM Power S822LC for Big Data (Supermicro) machines such as
|
||||
# P9 Boston (9006-22C, 9006-12C, 5104-22C) or P8 Briggs (8001-22C)
|
||||
# firmware update is done using pUpdate utility expected to be in the
|
||||
# specified data directory along with the update files .bin for BMC or .pnor for Host
|
||||
if ($output =~ /8001-22C|9006-22C/) {
|
||||
if ($output =~ /8001-22C|9006-22C|5104-22C|9006-12C/) {
|
||||
# Verify valid data directory was specified
|
||||
unless ($pUpdate_directory) {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback,
|
||||
"Directory name is required to update Boston or Briggs machines.");
|
||||
if (defined $directory_name) {
|
||||
unless (File::Spec->file_name_is_absolute($directory_name)) {
|
||||
# Directory name was passed in as relative path, prepend current working dir
|
||||
$directory_name = xCAT::Utils->full_path($directory_name, $::cwd);
|
||||
}
|
||||
# directory was passed in, verify it is valid
|
||||
if (-d $directory_name) {
|
||||
# Passed in directory name exists
|
||||
$pUpdate_directory = $directory_name;
|
||||
}
|
||||
else {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback, "Can not access data directory $directory_name");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback, "Directory name is required to update IBM Power S822LC for Big Data machines.");
|
||||
}
|
||||
# Verify specified directory contains pUpdate utility
|
||||
unless (-e "$pUpdate_directory/pUpdate") {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback,
|
||||
"Can not find pUpdate utility in data directory $pUpdate_directory.");
|
||||
}
|
||||
|
||||
# Verify specified directory contains executable pUpdate utility
|
||||
unless (-x "$pUpdate_directory/pUpdate") {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback,
|
||||
"Can not find executable pUpdate utility in data directory $pUpdate_directory.");
|
||||
"Execute permission is not set for pUpdate utility in data directory $pUpdate_directory.");
|
||||
}
|
||||
|
||||
# Verify there is at least one of update files inside data directory - .bin or .pnor
|
||||
@ -2111,7 +2120,7 @@ sub do_firmware_update {
|
||||
$exit_with_error_func->($sessdata->{node}, $callback,
|
||||
"Running ipmitool command $cmd failed: $output");
|
||||
}
|
||||
my $grs_version = $output =~ /OP8_v(\d*\.\d*_\d*\.\d*)/;
|
||||
my $grs_version = $output =~ /OP8_.*v(\d*\.\d*_\d*\.\d*)/;
|
||||
if ($grs_version =~ /\d\.(\d+)_(\d+\.\d+)/) {
|
||||
my $prim_grs_version = $1;
|
||||
my $sec_grs_version = $2;
|
||||
@ -2133,7 +2142,7 @@ sub do_firmware_update {
|
||||
"Running ipmitool command $cmd failed: $output");
|
||||
}
|
||||
# Check what firmware version is currently running on the machine
|
||||
if ($output =~ /OP8_v\d\.\d+_(\d+)\.\d+/) {
|
||||
if ($output =~ /OP8_.*v\d\.\d+_(\d+)\.\d+/) {
|
||||
my $frs_version = $1;
|
||||
if ($frs_version == 1) {
|
||||
$firestone_update_version = "810";
|
||||
@ -2174,7 +2183,7 @@ sub do_firmware_update {
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_firestone and
|
||||
if ($is_firestone and $firestone_update_version and
|
||||
(($firestone_update_version eq "820" and $htm_update_version eq "810") or
|
||||
($firestone_update_version eq "810" and $htm_update_version eq "820"))
|
||||
) {
|
||||
@ -2383,6 +2392,7 @@ RETRY_UPGRADE:
|
||||
|
||||
sub rflash {
|
||||
my $sessdata = shift;
|
||||
my $directory_flag = 0;
|
||||
if (isopenpower($sessdata)) {
|
||||
|
||||
# Do firmware update for firestone here.
|
||||
@ -2391,10 +2401,16 @@ sub rflash {
|
||||
if ($opt =~ /^(-c|--check)$/i) {
|
||||
$sessdata->{subcommand} = "check";
|
||||
# support verbose options for ipmitool command
|
||||
} elsif ($opt !~ /.*\.hpm$/i && $opt !~ /^-V{1,4}$|^--buffersize=|^--retry=|^-d=/) {
|
||||
$callback->({ error => "The option $opt is not supported or invalid update file specified",
|
||||
} elsif ($opt =~ /^-d$/) {
|
||||
# special handling if -d option which can be followed by a directory name
|
||||
$directory_flag = 1; # set a flag that directory option was given
|
||||
} elsif ($opt !~ /.*\.hpm$/i && $opt !~ /^-V{1,4}$|^--buffersize=|^--retry=/) {
|
||||
# An unexpected flag was passed, but it could be a directory name. Display error only if not -d option
|
||||
unless ($directory_flag) {
|
||||
$callback->({ error => "The option $opt is not supported or invalid update file specified",
|
||||
errorcode => 1 });
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2473,6 +2489,46 @@ sub do_rflash_process {
|
||||
$callback, $node, %allerrornodes);
|
||||
exit(1);
|
||||
}
|
||||
my $recover_image;
|
||||
if (grep(/^(--recover)$/, @{ $extra })) {
|
||||
if (@{ $extra } != 2) {
|
||||
xCAT::SvrUtils::sendmsg([ 1, "The command format for recovery is invalid. Only support 'rflash <noderange> --recover <bmc_file_path>'" ],
|
||||
$callback, $node);
|
||||
exit(1);
|
||||
}
|
||||
my @argv = @{ $extra };
|
||||
if ($argv[0] eq "--recover") {
|
||||
$recover_image = $argv[1];
|
||||
} elsif ($argv[1] eq "--recover") {
|
||||
$recover_image = $argv[0];
|
||||
}
|
||||
}
|
||||
if (defined($recover_image)) {
|
||||
if ($recover_image !~ /^\//) {
|
||||
$recover_image = xCAT::Utils->full_path($recover_image, $::cwd);
|
||||
}
|
||||
unless(-x "/usr/bin/tftp") {
|
||||
$callback->({ error => "Could not find executable file /usr/bin/tftp, please setup tftp client.",
|
||||
errorcode => 1 });
|
||||
exit(1);
|
||||
}
|
||||
my $bmcip = $_[0];
|
||||
my $cmd = "/usr/bin/tftp $bmcip -m binary -c put $recover_image ".basename($recover_image);
|
||||
my $output = xCAT::Utils->runcmd($cmd, -1);
|
||||
if ($::RUNCMD_RC != 0) {
|
||||
$callback->({ error => "Running tftp command \'$cmd\' failed. Error Code: $::RUNCMD_RC. Output: $output.",
|
||||
errorcode => 1 });
|
||||
exit(1);
|
||||
}
|
||||
# Sometimes tftp command retrun error message but without nonzero error code
|
||||
if($output) {
|
||||
$callback->({ error => "Running tftp command \'$cmd\' failed. Output: $output",
|
||||
errorcode => 1 });
|
||||
exit(1);
|
||||
}
|
||||
$callback->({ data => "$node: Successfully updated recovery image. BMC is restarting and will not be reachable for 5-10 minutes."});
|
||||
exit(0);
|
||||
}
|
||||
donode($node, @_);
|
||||
while (xCAT::IPMI->waitforrsp()) { yield }
|
||||
xCAT::Utils->release_lock($lock, $NON_BLOCK);
|
||||
|
@ -783,6 +783,15 @@ sub build_xmldesc {
|
||||
#prepare the xml hash for pci passthrough
|
||||
my @prdevarray;
|
||||
foreach my $devname (@passthrudevices) {
|
||||
#This is for SR-IOV vfio
|
||||
#Change vfio format 0000:01:00.2 to pci_0000_01_00_2
|
||||
if ( $devname =~ m/(\w:)+(\w)+.(\w)/ ){
|
||||
$devname =~ s/[:|.]/_/g;
|
||||
if ( $devname !~ /^pci_/ ) {
|
||||
$devname ="pci_".$devname
|
||||
}
|
||||
}
|
||||
|
||||
my $devobj = $hypconn->get_node_device_by_name($devname);
|
||||
unless ($devobj) {
|
||||
return -1;
|
||||
@ -1397,12 +1406,14 @@ sub makedom {
|
||||
}
|
||||
my $parseddom = $parser->parse_string($xml);
|
||||
my ($graphics) = $parseddom->findnodes("//graphics");
|
||||
if ($confdata->{vm}->{$node}->[0]->{vidpassword}) {
|
||||
$graphics->setAttribute("passwd", $confdata->{vm}->{$node}->[0]->{vidpassword});
|
||||
} else {
|
||||
$graphics->setAttribute("passwd", genpassword(20));
|
||||
if (defined($graphics)) {
|
||||
if ($confdata->{vm}->{$node}->[0]->{vidpassword}) {
|
||||
$graphics->setAttribute("passwd", $confdata->{vm}->{$node}->[0]->{vidpassword});
|
||||
} else {
|
||||
$graphics->setAttribute("passwd", genpassword(20));
|
||||
}
|
||||
$graphics->setAttribute("listen", '0.0.0.0');
|
||||
}
|
||||
$graphics->setAttribute("listen", '0.0.0.0');
|
||||
$xml = $parseddom->toString();
|
||||
eval {
|
||||
if ($::XCATSITEVALS{persistkvmguests}) {
|
||||
|
@ -325,7 +325,6 @@ sub donets
|
||||
# - compare net and mask values
|
||||
my $foundmatch = 0;
|
||||
foreach my $netn (@netlist) {
|
||||
|
||||
# split definition mask
|
||||
my ($dm1, $dm2, $dm3, $dm4) = split('\.', $nethash{$netn}{'mask'});
|
||||
|
||||
@ -359,7 +358,7 @@ sub donets
|
||||
if ($foundmatch) {
|
||||
next;
|
||||
}
|
||||
|
||||
|
||||
# add new network def
|
||||
$nettab->setAttribs({ 'net' => $net, 'mask' => $netmask }, { 'netname' => $netname, 'gateway' => $gateway, 'mgtifname' => $i });
|
||||
}
|
||||
@ -450,6 +449,7 @@ sub donets
|
||||
{ #should be the lines to think about, do something with U, and something else with UG
|
||||
|
||||
my $foundmatch = 0;
|
||||
my $netnamematch = 0;
|
||||
my $rsp;
|
||||
my $net;
|
||||
my $mask;
|
||||
@ -504,7 +504,11 @@ sub donets
|
||||
my ($n1, $n2, $n3, $n4) = split('\.', $net);
|
||||
|
||||
foreach my $netn (@netlist) {
|
||||
|
||||
# check if this netname is already defined
|
||||
if ( $netname eq $netn ) {
|
||||
$netnamematch = 1;
|
||||
last;
|
||||
}
|
||||
# split definition mask
|
||||
my ($dm1, $dm2, $dm3, $dm4) = split('\.', $nethash{$netn}{'mask'});
|
||||
|
||||
@ -544,6 +548,11 @@ sub donets
|
||||
push @{ $rsp->{data} }, " mtu=$mtu";
|
||||
}
|
||||
} else {
|
||||
# if this net entry exists, go to next line in networks table
|
||||
if ($netnamematch) {
|
||||
$callback->({ warning => "The network entry \'$netname\' already exists in xCAT networks table. Cannot create a definition for \'$netname\'" });
|
||||
next;
|
||||
}
|
||||
if (!$foundmatch) {
|
||||
$nettab->setAttribs({ 'net' => $net, 'mask' => $mask }, { 'netname' => $netname, 'mgtifname' => $mgtifname, 'gateway' => $gw, 'mtu' => $mtu });
|
||||
}
|
||||
|
@ -248,8 +248,16 @@ sub process_request {
|
||||
#for onie switch, lookup and set the switchtype via mac of mgt interface
|
||||
my $switchestab = xCAT::Table->new('switches');
|
||||
if ($switchestab) {
|
||||
my $switchtype=$xCAT::data::switchinfo::global_mac_identity{substr(lc($request->{_xcat_clientmac}->[0]),0,8)};
|
||||
if(defined $switchtype){
|
||||
my $switchtype;
|
||||
my $switchvendor=$xCAT::data::switchinfo::global_mac_identity{substr(lc($request->{_xcat_clientmac}->[0]),0,8)};
|
||||
if(defined $switchvendor){
|
||||
my $search_string = join '|', keys(%xCAT::data::switchinfo::global_switch_type);
|
||||
if ($switchvendor =~ /($search_string)/) {
|
||||
$switchtype=$xCAT::data::switchinfo::global_switch_type{$1};
|
||||
}
|
||||
}
|
||||
|
||||
if($switchtype){
|
||||
$switchestab->setNodeAttribs($node,{ switchtype => $switchtype });
|
||||
}
|
||||
$switchestab->close();
|
||||
@ -312,6 +320,9 @@ sub process_request {
|
||||
$hosttag = "$node-$ifinfo[1]";
|
||||
push @hostnames_to_update, $hosttag;
|
||||
}
|
||||
elsif (!inet_aton($node)) {
|
||||
xCAT::MsgUtils->message("S", "xcat.discovery.nodediscover: Can not resolve IP for the matching node:$node. Make sure \"makehosts\" and \"makedns\" have been run for $node.");
|
||||
}
|
||||
}
|
||||
#print Dumper($hosttag) . "\n";
|
||||
if ($hosttag) {
|
||||
@ -451,10 +462,16 @@ sub process_request {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
# Only BMC that doesn't support in-band configuration need to run rspconfig out-of-band, such as S822L running in OPAL model
|
||||
xCAT::MsgUtils->message("S", "No bmcinband specified, need to configure BMC out-of-band");
|
||||
xCAT::Utils->cleanup_for_powerLE_hardware_discovery($request, $doreq);
|
||||
if (defined($request->{bmc_node}) and defined($request->{bmc_node}->[0])) {
|
||||
my $bmc_node = $request->{bmc_node}->[0];
|
||||
if ($bmc_node =~ /\,/) {
|
||||
xCAT::MsgUtils->message("W", "Multiple BMC nodes matched with no bmcinband specified, please remove manually");
|
||||
} else {
|
||||
# Only BMC that doesn't support in-band configuration need to run rspconfig out-of-band, such as S822L running in OPAL model
|
||||
xCAT::MsgUtils->message("S", "No bmcinband specified, need to configure BMC out-of-band");
|
||||
xCAT::Utils->cleanup_for_powerLE_hardware_discovery($request, $doreq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -474,8 +491,6 @@ sub process_request {
|
||||
print $sock $restartstring;
|
||||
close($sock);
|
||||
|
||||
# sleep 2 seconds for genesis to complete the disocvery process
|
||||
sleep(2);
|
||||
|
||||
#Update the discoverydata table to indicate the successful discovery
|
||||
xCAT::DiscoveryUtils->update_discovery_data($request);
|
||||
|
@ -19,6 +19,7 @@ use JSON;
|
||||
use HTTP::Async;
|
||||
use HTTP::Cookies;
|
||||
use File::Basename;
|
||||
use File::Spec;
|
||||
use Data::Dumper;
|
||||
use Getopt::Long;
|
||||
use xCAT::OPENBMC;
|
||||
@ -42,6 +43,8 @@ $::POWER_STATE_QUIESCED = "quiesced";
|
||||
$::POWER_STATE_RESET = "reset";
|
||||
$::POWER_STATE_REBOOT = "reboot";
|
||||
$::UPLOAD_FILE = "";
|
||||
$::UPLOAD_FILE_VERSION = "";
|
||||
$::RSETBOOT_URL_PATH = "boot";
|
||||
|
||||
$::NO_ATTRIBUTES_RETURNED = "No attributes returned from the BMC.";
|
||||
|
||||
@ -94,6 +97,7 @@ my %sensor_units = (
|
||||
my $http_protocol="https";
|
||||
my $openbmc_url = "/org/openbmc";
|
||||
my $openbmc_project_url = "/xyz/openbmc_project";
|
||||
$::SOFTWARE_URL = "$openbmc_project_url/software";
|
||||
#-------------------------------------------------------
|
||||
|
||||
# The hash table to store method and url for request,
|
||||
@ -135,8 +139,8 @@ my %status_info = (
|
||||
},
|
||||
REVENTLOG_CLEAR_REQUEST => {
|
||||
method => "POST",
|
||||
init_url => "$openbmc_url/records/events/action/clear",
|
||||
data => "",
|
||||
init_url => "$openbmc_project_url/logging/action/deleteAll",
|
||||
data => "[]",
|
||||
},
|
||||
REVENTLOG_CLEAR_RESPONSE => {
|
||||
process => \&reventlog_response,
|
||||
@ -171,6 +175,13 @@ my %status_info = (
|
||||
RFLASH_UPDATE_CHECK_STATE_RESPONSE => {
|
||||
process => \&rflash_response,
|
||||
},
|
||||
RFLASH_UPDATE_CHECK_ID_REQUEST => {
|
||||
method => "GET",
|
||||
init_url => "$openbmc_project_url/software/enumerate",
|
||||
},
|
||||
RFLASH_UPDATE_CHECK_ID_RESPONSE => {
|
||||
process => \&rflash_response,
|
||||
},
|
||||
RFLASH_SET_PRIORITY_REQUEST => {
|
||||
method => "PUT",
|
||||
init_url => "$openbmc_project_url/software",
|
||||
@ -230,11 +241,6 @@ my %status_info = (
|
||||
init_url => "$openbmc_project_url/state/host0/attr/RequestedHostTransition",
|
||||
data => "xyz.openbmc_project.State.Host.Transition.Off",
|
||||
},
|
||||
RPOWER_RESET_REQUEST => {
|
||||
method => "PUT",
|
||||
init_url => "$openbmc_project_url/state/host0/attr/RequestedHostTransition",
|
||||
data => "xyz.openbmc_project.State.Host.Transition.Reboot",
|
||||
},
|
||||
RPOWER_RESET_RESPONSE => {
|
||||
process => \&rpower_response,
|
||||
},
|
||||
@ -246,9 +252,17 @@ my %status_info = (
|
||||
process => \&rpower_response,
|
||||
},
|
||||
|
||||
RSETBOOT_ENABLE_REQUEST => {
|
||||
method => "PUT",
|
||||
init_url => "$openbmc_project_url/control/host0/boot/one_time/attr/Enabled",
|
||||
data => '1',
|
||||
},
|
||||
RSETBOOT_ENABLE_RESPONSE => {
|
||||
process => \&rsetboot_response,
|
||||
},
|
||||
RSETBOOT_SET_REQUEST => {
|
||||
method => "PUT",
|
||||
init_url => "$openbmc_project_url/control/host0/boot_source/attr/BootSource",
|
||||
init_url => "$openbmc_project_url/control/host0/boot/one_time/attr/BootSource",
|
||||
data => "xyz.openbmc_project.Control.Boot.Source.Sources.",
|
||||
},
|
||||
RSETBOOT_SET_RESPONSE => {
|
||||
@ -256,7 +270,7 @@ my %status_info = (
|
||||
},
|
||||
RSETBOOT_STATUS_REQUEST => {
|
||||
method => "GET",
|
||||
init_url => "$openbmc_project_url/control/host0/boot_source",
|
||||
init_url => "$openbmc_project_url/control/host0/enumerate",
|
||||
},
|
||||
RSETBOOT_STATUS_RESPONSE => {
|
||||
process => \&rsetboot_response,
|
||||
@ -270,13 +284,21 @@ my %status_info = (
|
||||
process => \&rspconfig_response,
|
||||
},
|
||||
RSPCONFIG_SET_REQUEST => {
|
||||
method => "POST",
|
||||
init_url => "",
|
||||
data => "",
|
||||
method => "PUT",
|
||||
init_url => "$openbmc_project_url/network",
|
||||
data => "[]",
|
||||
},
|
||||
RSPCONFIG_SET_RESPONSE => {
|
||||
process => \&rspconfig_response,
|
||||
},
|
||||
RSPCONFIG_DHCP_REQUEST => {
|
||||
method => "POST",
|
||||
init_url => "$openbmc_project_url/network/action/Reset",
|
||||
data => "[]",
|
||||
},
|
||||
RSPCONFIG_DHCP_RESPONSE => {
|
||||
process => \&rspconfig_response,
|
||||
},
|
||||
RSPCONFIG_SSHCFG_REQUEST => {
|
||||
method => "GET",
|
||||
init_url => "",
|
||||
@ -365,6 +387,15 @@ sub preprocess_request {
|
||||
} else {
|
||||
$::OPENBMC_DEVEL = $request->{environment}->{XCAT_OPENBMC_DEVEL};
|
||||
}
|
||||
|
||||
if (ref($request->{environment}) eq 'ARRAY' and ref($request->{environment}->[0]->{XCAT_OPENBMC_FIRMWARE}) eq 'ARRAY') {
|
||||
$::OPENBMC_FW = $request->{environment}->[0]->{XCAT_OPENBMC_FIRMWARE}->[0];
|
||||
} elsif (ref($request->{environment}) eq 'ARRAY') {
|
||||
$::OPENBMC_FW = $request->{environment}->[0]->{XCAT_OPENBMC_FIRMWARE};
|
||||
} else {
|
||||
$::OPENBMC_FW = $request->{environment}->{XCAT_OPENBMC_FIRMWARE};
|
||||
}
|
||||
|
||||
##############################################
|
||||
|
||||
$callback = shift;
|
||||
@ -419,6 +450,7 @@ sub process_request {
|
||||
my $command = $request->{command}->[0];
|
||||
my $noderange = $request->{node};
|
||||
my $extrargs = $request->{arg};
|
||||
$::cwd = $request->{cwd}->[0];
|
||||
my @exargs = ($request->{arg});
|
||||
if (ref($extrargs)) {
|
||||
@exargs = @$extrargs;
|
||||
@ -461,7 +493,10 @@ sub process_request {
|
||||
$handle_id = xCAT::OPENBMC->new($async, $login_url, $content);
|
||||
$handle_id_node{$handle_id} = $node;
|
||||
$node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} };
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug POST $login_url -d $content", $callback, $node) if ($xcatdebugmode);
|
||||
if ($xcatdebugmode) {
|
||||
my $debug_info = "curl -k -c cjar -H \"Content-Type: application/json\" -d '{ \"data\": [\"$node_info{$node}{username}\", \"xxxxxx\"] }' $login_url";
|
||||
process_debug_info($node, $debug_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,7 +547,7 @@ sub parse_args {
|
||||
return ([ 1, "Error parsing arguments." ]) if ($option !~ /V|verbose/);
|
||||
}
|
||||
|
||||
if (scalar(@ARGV) >= 2 and ($command =~ /rpower|rinv|rsetboot|rvitals/)) {
|
||||
if (scalar(@ARGV) >= 2 and ($command =~ /rpower|rinv|rvitals/)) {
|
||||
return ([ 1, "Only one option is supported at the same time for $command" ]);
|
||||
} elsif (scalar(@ARGV) == 0 and $command =~ /rpower|rspconfig|rflash/) {
|
||||
return ([ 1, "No option specified for $command" ]);
|
||||
@ -528,6 +563,13 @@ sub parse_args {
|
||||
unless ($subcommand =~ /^on$|^off$|^softoff$|^reset$|^boot$|^bmcreboot$|^bmcstate$|^status$|^stat$|^state$/) {
|
||||
return ([ 1, "Unsupported command: $command $subcommand" ]);
|
||||
}
|
||||
if ($subcommand =~ /^reset$|^boot$/) {
|
||||
$check = unsupported($callback);
|
||||
if (ref($check) eq "ARRAY") {
|
||||
@$check[1] = "Command $command $subcommand is not supported now.\nPlease run 'rpower <node> off' and then 'rpower <node> on' instead.";
|
||||
return $check;
|
||||
}
|
||||
}
|
||||
} elsif ($command eq "rinv") {
|
||||
$subcommand = "all" if (!defined($ARGV[0]));
|
||||
unless ($subcommand =~ /^model$|^serial$|^firm$|^cpu$|^dimm$|^all$/) {
|
||||
@ -541,10 +583,6 @@ sub parse_args {
|
||||
return ([ 1, "Unsupported command: $command $subcommand" ]);
|
||||
}
|
||||
} elsif ($command eq "reventlog") {
|
||||
#
|
||||
# disable function until fully tested
|
||||
#
|
||||
$check = unsupported($callback); if (ref($check) eq "ARRAY") { return $check; }
|
||||
my $option_s = 0;
|
||||
unless (GetOptions("s" => \$option_s,)) {
|
||||
return ([1, "Error parsing arguments." ]);
|
||||
@ -554,30 +592,33 @@ sub parse_args {
|
||||
return ([ 1, "Unsupported command: $command $subcommand" ]);
|
||||
}
|
||||
} elsif ($command eq "rspconfig") {
|
||||
#
|
||||
# disable function until fully tested
|
||||
#
|
||||
$check = unsupported($callback); # Check later for each subcommand: if (ref($check) eq "ARRAY") { return $check; }
|
||||
my $setorget;
|
||||
foreach $subcommand (@ARGV) {
|
||||
if ($subcommand =~ /^(\w+)=(.*)/) {
|
||||
return ([ 1, "Can not configure and display nodes' value at the same time" ]) if ($setorget and $setorget eq "get");
|
||||
my $key = $1;
|
||||
my $value = $2;
|
||||
return ([ 1, "Unsupported command: $command $key" ]) unless ($key =~ /^ip$|^netmask$|^gateway$|^vlan$/);
|
||||
return ([ 1, "Unsupported command: $command $key" ]) unless ($key =~ /^ip$|^netmask$|^gateway$|^hostname$|^vlan$/);
|
||||
|
||||
my $nodes_num = @$noderange;
|
||||
return ([ 1, "Invalid parameter for option $key" ]) unless ($value);
|
||||
return ([ 1, "Invalid parameter for option $key: $value" ]) unless (xCAT::NetworkUtils->isIpaddr($value));
|
||||
return ([ 1, "Invalid parameter for option $key: $value" ]) if ($key =~ /^netmask$|^gateway$/ and !xCAT::NetworkUtils->isIpaddr($value));
|
||||
if ($key eq "ip") {
|
||||
return ([ 1, "Can not configure more than 1 nodes' ip at the same time" ]) if ($nodes_num >= 2);
|
||||
return ([ 1, "Can not configure more than 1 nodes' ip at the same time" ]) if ($nodes_num >= 2 and $value ne "dhcp");
|
||||
if ($value ne "dhcp" and !xCAT::NetworkUtils->isIpaddr($value)) {
|
||||
return ([ 1, "Invalid parameter for option $key: $value" ]);
|
||||
}
|
||||
}
|
||||
$setorget = "set";
|
||||
if (ref($check) eq "ARRAY") { return $check; }
|
||||
} elsif ($subcommand =~ /^ip$|^netmask$|^gateway$|^vlan$/) {
|
||||
#
|
||||
# disable function until fully tested
|
||||
#
|
||||
unless (($key eq "ip" and $value eq "dhcp") or $key eq "hostname") {
|
||||
$check = unsupported($callback); if (ref($check) eq "ARRAY") { return $check; }
|
||||
}
|
||||
} elsif ($subcommand =~ /^ip$|^netmask$|^gateway$|^hostname$|^vlan$/) {
|
||||
return ([ 1, "Can not configure and display nodes' value at the same time" ]) if ($setorget and $setorget eq "set");
|
||||
$setorget = "get";
|
||||
if (ref($check) eq "ARRAY") { return $check; }
|
||||
} elsif ($subcommand =~ /^sshcfg$/) {
|
||||
$setorget = ""; # SSH Keys are copied using a RShellAPI, not REST API
|
||||
} else {
|
||||
@ -590,11 +631,6 @@ sub parse_args {
|
||||
return ([ 1, "Unsupported command: $command $subcommand" ]);
|
||||
}
|
||||
} elsif ($command eq "rflash") {
|
||||
#
|
||||
# disable function until fully supported by openbmc
|
||||
# Currently waiting for issue https://github.com/openbmc/openbmc/issues/2074 to be fixed
|
||||
#
|
||||
$check = unsupported($callback); if (ref($check) eq "ARRAY") { return $check; }
|
||||
my $filename_passed = 0;
|
||||
my $updateid_passed = 0;
|
||||
my $option_flag;
|
||||
@ -616,7 +652,7 @@ sub parse_args {
|
||||
}
|
||||
if ($filename_passed) {
|
||||
# Filename was passed, check flags allowed with file
|
||||
if ($option_flag !~ /^-c$|^--check$|^-d$|^--delete$|^-u$|^--upload$/) {
|
||||
if ($option_flag !~ /^-c$|^--check$|^-u$|^--upload$|^-a$|^--activate$/) {
|
||||
return ([ 1, "Invalid option specified when a file is provided: $option_flag" ]);
|
||||
}
|
||||
}
|
||||
@ -655,7 +691,9 @@ sub parse_command_status {
|
||||
my $subcommands = shift;
|
||||
my $subcommand;
|
||||
|
||||
if ($$subcommands[-1] =~ /V|verbose/) {
|
||||
return if ($command eq "getopenbmccons");
|
||||
|
||||
if ($$subcommands[-1] and $$subcommands[-1] =~ /V|verbose/) {
|
||||
$::VERBOSE = 1;
|
||||
pop(@$subcommands);
|
||||
}
|
||||
@ -687,19 +725,24 @@ sub parse_command_status {
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_SOFTOFF_REQUEST";
|
||||
$next_status{RPOWER_SOFTOFF_REQUEST} = "RPOWER_OFF_RESPONSE";
|
||||
} elsif ($subcommand eq "reset") {
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_RESET_REQUEST";
|
||||
$next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE";
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST";
|
||||
$next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE";
|
||||
$next_status{RPOWER_STATUS_RESPONSE}{OFF} = "DO_NOTHING";
|
||||
$next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_OFF_REQUEST";
|
||||
$next_status{RPOWER_OFF_REQUEST} = "RPOWER_OFF_RESPONSE";
|
||||
$next_status{RPOWER_OFF_RESPONSE} = "RPOWER_ON_REQUEST";
|
||||
$next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE";
|
||||
$status_info{RPOWER_ON_RESPONSE}{argv} = "$subcommand";
|
||||
} elsif ($subcommand =~ /^bmcstate$|^status$|^state$|^stat$/) {
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST";
|
||||
$next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE";
|
||||
$status_info{RPOWER_STATUS_RESPONSE}{argv} = "$subcommand";
|
||||
} elsif ($subcommand eq "boot") {
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_STATUS_REQUEST";
|
||||
$next_status{RPOWER_STATUS_REQUEST} = "RPOWER_STATUS_RESPONSE";
|
||||
$next_status{RPOWER_STATUS_RESPONSE}{OFF} = "RPOWER_ON_REQUEST";
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_OFF_REQUEST";
|
||||
$next_status{RPOWER_OFF_REQUEST} = "RPOWER_OFF_RESPONSE";
|
||||
$next_status{RPOWER_OFF_RESPONSE} = "RPOWER_ON_REQUEST";
|
||||
$next_status{RPOWER_ON_REQUEST} = "RPOWER_ON_RESPONSE";
|
||||
$next_status{RPOWER_STATUS_RESPONSE}{ON} = "RPOWER_RESET_REQUEST";
|
||||
$next_status{RPOWER_RESET_REQUEST} = "RPOWER_RESET_RESPONSE";
|
||||
$status_info{RPOWER_ON_RESPONSE}{argv} = "$subcommand";
|
||||
} elsif ($subcommand eq "bmcreboot") {
|
||||
$next_status{LOGIN_RESPONSE} = "RPOWER_BMCREBOOT_REQUEST";
|
||||
$next_status{RPOWER_BMCREBOOT_REQUEST} = "RPOWER_RESET_RESPONSE";
|
||||
@ -731,9 +774,32 @@ sub parse_command_status {
|
||||
}
|
||||
|
||||
if ($command eq "rsetboot") {
|
||||
$subcommand = $$subcommands[0];
|
||||
if ($$subcommands[-1] and $$subcommands[-1] eq "-p") {
|
||||
pop(@$subcommands);
|
||||
$status_info{RSETBOOT_ENABLE_REQUEST}{data} = '0';
|
||||
$status_info{RSETBOOT_SET_REQUEST}{init_url} = "$openbmc_project_url/control/host0/boot/attr/BootSource";
|
||||
}
|
||||
|
||||
if (defined($$subcommands[0])) {
|
||||
$subcommand = $$subcommands[0];
|
||||
} else {
|
||||
$subcommand = "stat";
|
||||
}
|
||||
if ($subcommand =~ /^hd$|^net$|^cd$|^default$|^def$/) {
|
||||
$next_status{LOGIN_RESPONSE} = "RSETBOOT_SET_REQUEST";
|
||||
if (defined($::OPENBMC_FW) && ($::OPENBMC_FW < 1738)) {
|
||||
#
|
||||
# In 1738, the endpount URL changed. In order to support the older URL as a work around, allow for a environment
|
||||
# variable to change this value.
|
||||
#
|
||||
$::RSETBOOT_URL_PATH = "boot_source";
|
||||
$status_info{RSETBOOT_SET_REQUEST}{init_url} = "$openbmc_project_url/control/host0/$::RSETBOOT_URL_PATH/attr/BootSource";
|
||||
$status_info{RSETBOOT_STATUS_REQUEST}{init_url} = "$openbmc_project_url/control/host0/$::RSETBOOT_URL_PATH";
|
||||
$next_status{LOGIN_RESPONSE} = "RSETBOOT_SET_REQUEST";
|
||||
} else {
|
||||
$next_status{LOGIN_RESPONSE} = "RSETBOOT_ENABLE_REQUEST";
|
||||
$next_status{RSETBOOT_ENABLE_REQUEST} = "RSETBOOT_ENABLE_RESPONSE";
|
||||
$next_status{RSETBOOT_ENABLE_RESPONSE} = "RSETBOOT_SET_REQUEST";
|
||||
}
|
||||
$next_status{RSETBOOT_SET_REQUEST} = "RSETBOOT_SET_RESPONSE";
|
||||
if ($subcommand eq "net") {
|
||||
$status_info{RSETBOOT_SET_REQUEST}{data} .= "Network";
|
||||
@ -754,7 +820,7 @@ sub parse_command_status {
|
||||
|
||||
if ($command eq "reventlog") {
|
||||
my $option_s = 0;
|
||||
if ($$subcommands[-1] eq "-s") {
|
||||
if ($$subcommands[-1] and $$subcommands[-1] eq "-s") {
|
||||
$option_s = 1;
|
||||
pop(@$subcommands);
|
||||
}
|
||||
@ -768,8 +834,6 @@ sub parse_command_status {
|
||||
if ($subcommand eq "clear") {
|
||||
$next_status{LOGIN_RESPONSE} = "REVENTLOG_CLEAR_REQUEST";
|
||||
$next_status{REVENTLOG_CLEAR_REQUEST} = "REVENTLOG_CLEAR_RESPONSE";
|
||||
xCAT::SvrUtils::sendmsg("Command $command is not available now!", $callback);
|
||||
return 1;
|
||||
} else {
|
||||
$next_status{LOGIN_RESPONSE} = "REVENTLOG_REQUEST";
|
||||
$next_status{REVENTLOG_REQUEST} = "REVENTLOG_RESPONSE";
|
||||
@ -781,7 +845,7 @@ sub parse_command_status {
|
||||
if ($command eq "rspconfig") {
|
||||
my @options = ();
|
||||
foreach $subcommand (@$subcommands) {
|
||||
if ($subcommand =~ /^ip$|^netmask$|^gateway$|^vlan$/) {
|
||||
if ($subcommand =~ /^ip$|^netmask$|^gateway$|^hostname$|^vlan$/) {
|
||||
$next_status{LOGIN_RESPONSE} = "RSPCONFIG_GET_REQUEST";
|
||||
$next_status{RSPCONFIG_GET_REQUEST} = "RSPCONFIG_GET_RESPONSE";
|
||||
push @options, $subcommand;
|
||||
@ -795,15 +859,33 @@ sub parse_command_status {
|
||||
} elsif ($subcommand =~ /^(\w+)=(.+)/) {
|
||||
my $key = $1;
|
||||
my $value = $2;
|
||||
$next_status{LOGIN_RESPONSE} = "RSPCONFIG_SET_REQUEST";
|
||||
$next_status{RSPCONFIG_SET_REQUEST} = "RSPCONFIG_SET_RESPONSE";
|
||||
$next_status{RSPCONFIG_SET_RESPONSE} = "RSPCONFIG_GET_REQUEST";
|
||||
$next_status{RSPCONFIG_GET_REQUEST} = "RSPCONFIG_GET_RESPONSE";
|
||||
if ($key eq "ip") {
|
||||
$status_info{RSPCONFIG_SET_RESPONSE}{ip} = $value;
|
||||
if ($key eq "ip" and $value eq "dhcp") {
|
||||
$next_status{LOGIN_RESPONSE} = "RSPCONFIG_DHCP_REQUEST";
|
||||
$next_status{RSPCONFIG_DHCP_REQUEST} = "RSPCONFIG_DHCP_RESPONSE";
|
||||
$next_status{RSPCONFIG_DHCP_RESPONSE} = "RPOWER_BMCREBOOT_REQUEST";
|
||||
$next_status{RPOWER_BMCREBOOT_REQUEST} = "RPOWER_RESET_RESPONSE";
|
||||
$status_info{RPOWER_RESET_RESPONSE}{argv} = "bmcreboot";
|
||||
} elsif ($key =~ /^hostname$/) {
|
||||
$next_status{LOGIN_RESPONSE} = "RSPCONFIG_SET_REQUEST";
|
||||
$next_status{RSPCONFIG_SET_REQUEST} = "RSPCONFIG_SET_RESPONSE";
|
||||
$next_status{RSPCONFIG_SET_RESPONSE} = "RSPCONFIG_GET_REQUEST";
|
||||
$next_status{RSPCONFIG_GET_REQUEST} = "RSPCONFIG_GET_RESPONSE";
|
||||
|
||||
$status_info{RSPCONFIG_SET_REQUEST}{data} = "$value";
|
||||
$status_info{RSPCONFIG_SET_REQUEST}{init_url} .= "/config/attr/HostName";
|
||||
push @options, $key;
|
||||
|
||||
} else {
|
||||
$next_status{LOGIN_RESPONSE} = "RSPCONFIG_SET_REQUEST";
|
||||
$next_status{RSPCONFIG_SET_REQUEST} = "RSPCONFIG_SET_RESPONSE";
|
||||
$next_status{RSPCONFIG_SET_RESPONSE} = "RSPCONFIG_GET_REQUEST";
|
||||
$next_status{RSPCONFIG_GET_REQUEST} = "RSPCONFIG_GET_RESPONSE";
|
||||
if ($key eq "ip") {
|
||||
$status_info{RSPCONFIG_SET_RESPONSE}{ip} = $value;
|
||||
}
|
||||
$status_info{RSPCONFIG_SET_REQUEST}{data} = ""; # wait for interface, ip/netmask/gateway is $value
|
||||
push @options, $key;
|
||||
}
|
||||
$status_info{RSPCONFIG_SET_REQUEST}{data} = ""; # wait for interface, ip/netmask/gateway is $value
|
||||
push @options, $key;
|
||||
}
|
||||
}
|
||||
$status_info{RSPCONFIG_GET_RESPONSE}{argv} = join(",", @options);
|
||||
@ -828,6 +910,7 @@ sub parse_command_status {
|
||||
my $upload = 0;
|
||||
my $activate = 0;
|
||||
my $update_file;
|
||||
my $upload_and_activate = 0;
|
||||
|
||||
foreach $subcommand (@$subcommands) {
|
||||
if ($subcommand =~ /-c|--check/) {
|
||||
@ -845,33 +928,51 @@ sub parse_command_status {
|
||||
}
|
||||
}
|
||||
|
||||
my $filename = undef;
|
||||
my $file_id = undef;
|
||||
my $grep_cmd = "/usr/bin/grep -a";
|
||||
my $version_tag = '"version=IBM"';
|
||||
my $version_tag = '"^version="';
|
||||
my $purpose_tag = '"purpose="';
|
||||
my $purpose_value;
|
||||
my $version_value;
|
||||
if (defined $update_file) {
|
||||
# Filename or file id was specified
|
||||
if ($update_file =~ /.*\.tar$/) {
|
||||
# Filename ending on .tar was specified
|
||||
$filename = $update_file;
|
||||
$::UPLOAD_FILE = $update_file; # Save filename to upload
|
||||
if (File::Spec->file_name_is_absolute($update_file)) {
|
||||
$::UPLOAD_FILE = $update_file;
|
||||
}
|
||||
else {
|
||||
# If relative file path was given, convert it to absolute
|
||||
$::UPLOAD_FILE = xCAT::Utils->full_path($update_file, $::cwd);
|
||||
}
|
||||
# Verify file exists and is readable
|
||||
unless (-r $filename) {
|
||||
xCAT::SvrUtils::sendmsg([1,"Cannot access $filename"], $callback);
|
||||
unless (-r $::UPLOAD_FILE) {
|
||||
xCAT::SvrUtils::sendmsg([1,"Cannot access $::UPLOAD_FILE"], $callback);
|
||||
return 1;
|
||||
}
|
||||
if ($check_version) {
|
||||
# Display firmware version of the specified .tar file
|
||||
my $firmware_version_in_file = `$grep_cmd $version_tag $filename`;
|
||||
my $purpose_version_in_file = `$grep_cmd $purpose_tag $filename`;
|
||||
if ($activate) {
|
||||
# Activate flag was specified together with a update file. We want to
|
||||
# upload the file and activate it.
|
||||
$upload_and_activate = 1;
|
||||
$activate = 0;
|
||||
}
|
||||
|
||||
if ($check_version | $upload_and_activate) {
|
||||
# Extract Host version for the update file
|
||||
my $firmware_version_in_file = `$grep_cmd $version_tag $::UPLOAD_FILE`;
|
||||
my $purpose_version_in_file = `$grep_cmd $purpose_tag $::UPLOAD_FILE`;
|
||||
chomp($firmware_version_in_file);
|
||||
chomp($purpose_version_in_file);
|
||||
my ($purpose_string,$purpose_value) = split("=", $purpose_version_in_file);
|
||||
my ($version_string,$version_value) = split("=", $firmware_version_in_file);
|
||||
(my $purpose_string,$purpose_value) = split("=", $purpose_version_in_file);
|
||||
(my $version_string,$version_value) = split("=", $firmware_version_in_file);
|
||||
if ($purpose_value =~ /host/) {
|
||||
$purpose_value = "Host";
|
||||
}
|
||||
$::UPLOAD_FILE_VERSION = $version_value;
|
||||
}
|
||||
|
||||
if ($check_version) {
|
||||
# Display firmware version of the specified .tar file
|
||||
xCAT::SvrUtils::sendmsg("TAR $purpose_value Firmware Product Version\: $version_value", $callback);
|
||||
}
|
||||
}
|
||||
@ -919,9 +1020,15 @@ sub parse_command_status {
|
||||
$next_status{"RFLASH_SET_PRIORITY_REQUEST"} = "RFLASH_SET_PRIORITY_RESPONSE";
|
||||
$next_status{"RFLASH_SET_PRIORITY_RESPONSE"} = "RFLASH_UPDATE_CHECK_STATE_REQUEST";
|
||||
}
|
||||
if ($upload_and_activate) {
|
||||
# Upload specified update file to BMC
|
||||
$next_status{LOGIN_RESPONSE} = "RFLASH_FILE_UPLOAD_REQUEST";
|
||||
$next_status{"RFLASH_FILE_UPLOAD_REQUEST"} = "RFLASH_FILE_UPLOAD_RESPONSE";
|
||||
$next_status{"RFLASH_FILE_UPLOAD_RESPONSE"} = "RFLASH_UPDATE_CHECK_ID_REQUEST";
|
||||
$next_status{"RFLASH_UPDATE_CHECK_ID_REQUEST"} = "RFLASH_UPDATE_CHECK_ID_RESPONSE";
|
||||
}
|
||||
}
|
||||
|
||||
print Dumper(\%next_status) . "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -984,8 +1091,6 @@ sub parse_node_info {
|
||||
}
|
||||
}
|
||||
|
||||
print Dumper(\%node_info) ."\n";
|
||||
|
||||
return $rst;
|
||||
}
|
||||
|
||||
@ -1019,7 +1124,7 @@ sub gen_send_request {
|
||||
$method = $status_info{ $node_info{$node}{cur_status} }{method};
|
||||
}
|
||||
|
||||
if ($status_info{ $node_info{$node}{cur_status} }{data}) {
|
||||
if (defined($status_info{ $node_info{$node}{cur_status} }{data})) {
|
||||
# Handle boolean values by create the json objects without wrapping with quotes
|
||||
if ($status_info{ $node_info{$node}{cur_status} }{data} =~ /^1$|^true$|^True$|^0$|^false$|^False$/) {
|
||||
$content = '{"data":' . $status_info{ $node_info{$node}{cur_status} }{data} . '}';
|
||||
@ -1042,19 +1147,20 @@ sub gen_send_request {
|
||||
$handle_id_node{$handle_id} = $node;
|
||||
$node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} };
|
||||
|
||||
my $debug_info;
|
||||
if ($method eq "GET") {
|
||||
$debug_info = "$method $request_url";
|
||||
} else {
|
||||
if ($::UPLOAD_FILE) {
|
||||
# Slightly different debug message when doing a file upload
|
||||
$debug_info = "$method $request_url -T " . $::UPLOAD_FILE;
|
||||
}
|
||||
else {
|
||||
$debug_info = "$method $request_url -d $content";
|
||||
if ($xcatdebugmode) {
|
||||
my $debug_info;
|
||||
if ($method eq "GET") {
|
||||
$debug_info = "curl -k -b cjar -X $method -H \"Content-Type: application/json\" $request_url";
|
||||
} else {
|
||||
if ($::UPLOAD_FILE) {
|
||||
# Slightly different debug message when doing a file upload
|
||||
$debug_info = "curl -k -b cjar -X $method -H \"Content-Type: application/json\" -T $::UPLOAD_FILE $request_url";
|
||||
} else {
|
||||
$debug_info = "curl -k -b cjar -X $method -H \"Content-Type: application/json\" -d '$content' $request_url";
|
||||
}
|
||||
}
|
||||
process_debug_info($node, $debug_info);
|
||||
}
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug $debug_info", $callback, $node) if ($xcatdebugmode);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1078,8 +1184,10 @@ sub deal_with_response {
|
||||
|
||||
delete $handle_id_node{$handle_id};
|
||||
|
||||
my $debug_info = lc ($node_info{$node}{cur_status}) . " " . $response->status_line;
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug $debug_info", $callback, $node) if ($xcatdebugmode);
|
||||
if ($xcatdebugmode) {
|
||||
my $debug_info = lc ($node_info{$node}{cur_status}) . " " . $response->status_line;
|
||||
process_debug_info($node, $debug_info);
|
||||
}
|
||||
|
||||
if ($response->status_line ne $::RESPONSE_OK) {
|
||||
my $error;
|
||||
@ -1119,6 +1227,26 @@ sub deal_with_response {
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 process_debug_info
|
||||
|
||||
print debug info and add to log
|
||||
Input:
|
||||
$node: nodename which want to process ingo
|
||||
$debug_msg: Info for debug
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub process_debug_info {
|
||||
my $node = shift;
|
||||
my $debug_msg = shift;
|
||||
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug $debug_msg", $callback, $node);
|
||||
xCAT::MsgUtils->trace(0, "D", "$flag_debug $node $debug_msg");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 login_response
|
||||
|
||||
Deal with response of login
|
||||
@ -1163,14 +1291,18 @@ sub rpower_response {
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RPOWER_ON_RESPONSE") {
|
||||
if ($response_info->{'message'} eq $::RESPONSE_OK) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_ON", $callback, $node);
|
||||
if ($status_info{RPOWER_ON_RESPONSE}{argv}) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_RESET", $callback, $node);
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_ON", $callback, $node);
|
||||
}
|
||||
$new_status{$::STATUS_POWERING_ON} = [$node];
|
||||
}
|
||||
}
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RPOWER_OFF_RESPONSE") {
|
||||
if ($response_info->{'message'} eq $::RESPONSE_OK) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$new_status{$::STATUS_POWERING_OFF} = [$node];
|
||||
}
|
||||
}
|
||||
@ -1178,10 +1310,7 @@ sub rpower_response {
|
||||
if ($node_info{$node}{cur_status} eq "RPOWER_RESET_RESPONSE") {
|
||||
if ($response_info->{'message'} eq $::RESPONSE_OK) {
|
||||
if (defined $status_info{RPOWER_RESET_RESPONSE}{argv} and $status_info{RPOWER_RESET_RESPONSE}{argv} =~ /bmcreboot$/) {
|
||||
my $bmc_node = "$node BMC";
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_REBOOT", $callback, $bmc_node);
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_RESET", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("BMC $::POWER_STATE_REBOOT", $callback, $node);
|
||||
}
|
||||
$new_status{$::STATUS_POWERING_ON} = [$node];
|
||||
}
|
||||
@ -1189,7 +1318,8 @@ sub rpower_response {
|
||||
|
||||
xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%new_status, 1) if (%new_status);
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE" and !$next_status{ $node_info{$node}{cur_status} }) {
|
||||
my $all_status;
|
||||
if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") {
|
||||
my $bmc_state = "";
|
||||
my $bmc_transition_state = "";
|
||||
my $chassis_state = "";
|
||||
@ -1210,53 +1340,62 @@ sub rpower_response {
|
||||
$host_transition_state = $response_info->{'data'}->{$type}->{RequestedHostTransition};
|
||||
}
|
||||
}
|
||||
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug State CurrentBMCState=$bmc_state", $callback, $node) if ($xcatdebugmode);
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug State RequestedBMCTransition=$bmc_transition_state", $callback, $node) if ($xcatdebugmode);
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug State CurrentPowerState=$chassis_state", $callback, $node) if ($xcatdebugmode);
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug State RequestedPowerTransition=$chassis_transition_state", $callback, $node) if ($xcatdebugmode);
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug State CurrentHostState=$host_state", $callback, $node) if ($xcatdebugmode);
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug State RequestedHostTransition=$host_transition_state", $callback, $node) if ($xcatdebugmode);
|
||||
|
||||
if (defined $status_info{RPOWER_STATUS_RESPONSE}{argv} and $status_info{RPOWER_STATUS_RESPONSE}{argv} =~ /bmcstate$/) {
|
||||
my $bmc_node = "$node BMC";
|
||||
my $bmc_short_state = (split(/\./, $bmc_state))[-1];
|
||||
xCAT::SvrUtils::sendmsg($bmc_short_state, $callback, $bmc_node);
|
||||
xCAT::SvrUtils::sendmsg("BMC $bmc_short_state", $callback, $node);
|
||||
} else {
|
||||
if ($chassis_state =~ /Off$/) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_OFF;
|
||||
} elsif ($chassis_state =~ /On$/) {
|
||||
if ($host_state =~ /Off$/) {
|
||||
# State is off, but check if it is transitioning
|
||||
if ($host_transition_state =~ /On$/) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_POWERING_ON", $callback, $node);
|
||||
}
|
||||
else {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node);
|
||||
#xCAT::SvrUtils::sendmsg("$::POWER_STATE_POWERING_ON", $callback, $node);
|
||||
# ignore transition state until get stable firmware
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_OFF;
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_OFF", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_OFF;
|
||||
}
|
||||
} elsif ($host_state =~ /Quiesced$/) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_QUIESCED", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_QUIESCED", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_ON;
|
||||
} elsif ($host_state =~ /Running$/) {
|
||||
# State is on, but check if it is transitioning
|
||||
if ($host_transition_state =~ /Off$/) {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_POWERING_OFF", $callback, $node);
|
||||
}
|
||||
else {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_ON", $callback, $node);
|
||||
#xCAT::SvrUtils::sendmsg("$::POWER_STATE_POWERING_OFF", $callback, $node);
|
||||
# ignore transition state until get stable firmware
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_ON", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_ON;
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_ON", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_ON;
|
||||
}
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Unexpected host state=$host_state", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("Unexpected host state=$host_state", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_ON;
|
||||
}
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Unexpected chassis state=$chassis_state", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("Unexpected chassis state=$chassis_state", $callback, $node) if (!$next_status{ $node_info{$node}{cur_status} });
|
||||
$all_status = $::POWER_STATE_ON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($next_status{ $node_info{$node}{cur_status} }) {
|
||||
if ($node_info{$node}{cur_status} eq "RPOWER_STATUS_RESPONSE") {
|
||||
if ($response_info->{'data'}->{CurrentHostState} =~ /Off$/) {
|
||||
$node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{OFF};
|
||||
if ($all_status eq "$::POWER_STATE_OFF") {
|
||||
if ($next_status{ $node_info{$node}{cur_status} }{OFF} eq "DO_NOTHING") {
|
||||
xCAT::SvrUtils::sendmsg("$::POWER_STATE_RESET", $callback, $node);
|
||||
$node_info{$node}{cur_status} = "";
|
||||
$wait_node_num--;
|
||||
return;
|
||||
} else {
|
||||
$node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{OFF};
|
||||
}
|
||||
} else {
|
||||
$node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} }{ON};
|
||||
}
|
||||
@ -1310,15 +1449,23 @@ sub rinv_response {
|
||||
my $purpose_value = uc ((split(/\./, $content{Purpose}))[-1]);
|
||||
$purpose_value = "[$sw_id]$purpose_value";
|
||||
my $activation_value = (split(/\./, $content{Activation}))[-1];
|
||||
my $priority_value = -1;
|
||||
if (defined($content{Priority})) {
|
||||
$priority_value = $content{Priority};
|
||||
}
|
||||
#
|
||||
# For 'rinv firm', only print Active software, unless verbose is specified
|
||||
#
|
||||
if ($activation_value =~ "Active" or $::VERBOSE) {
|
||||
if (($activation_value =~ "Active" and $priority_value == 0) or $::VERBOSE) {
|
||||
#
|
||||
# The space below between "Firmware Product Version:" and $content{Version} is intentional
|
||||
# to cause the sorting of this line before any additional info lines
|
||||
#
|
||||
$content_info = "$purpose_value Firmware Product: $content{Version} ($activation_value)";
|
||||
if ($priority_value == 0) {
|
||||
# For now, indicate priority 0 software levels with an '*'
|
||||
$content_info .= "*";
|
||||
}
|
||||
push (@sorted_output, $content_info);
|
||||
|
||||
if (defined($content{ExtendedVersion}) and $content{ExtendedVersion} ne "") {
|
||||
@ -1334,8 +1481,8 @@ sub rinv_response {
|
||||
}
|
||||
} else {
|
||||
if (! defined $content{Present}) {
|
||||
# This should never happen, but if we find this, contact firmware team to fix...
|
||||
xCAT::SvrUtils::sendmsg("ERROR: Invalid data for $key_url, contact firmware team!", $callback, $node);
|
||||
# If the Present field is not part of the attribute, then it's most likely a callout
|
||||
# Do not print as part of the inventory response
|
||||
next;
|
||||
}
|
||||
|
||||
@ -1437,13 +1584,29 @@ sub rsetboot_response {
|
||||
my $response_info = decode_json $response->content;
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RSETBOOT_STATUS_RESPONSE") {
|
||||
if ($response_info->{'data'}->{BootSource} =~ /Disk$/) {
|
||||
my $one_time_enabled;
|
||||
my $bootsource;
|
||||
if (defined($::OPENBMC_FW) && ($::OPENBMC_FW < 1738)) {
|
||||
$bootsource = $response_info->{'data'}->{BootSource};
|
||||
} else {
|
||||
foreach my $key_url (keys %{$response_info->{data}}) {
|
||||
my %content = %{ ${ $response_info->{data} }{$key_url} };
|
||||
if ($key_url =~ /boot\/one_time/) {
|
||||
$one_time_enabled = $content{Enabled};
|
||||
$bootsource = $content{BootSource} if ($one_time_enabled);
|
||||
} elsif ($key_url =~ /\/boot$/) {
|
||||
$bootsource = $content{BootSource} unless ($one_time_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($bootsource =~ /Disk$/) {
|
||||
xCAT::SvrUtils::sendmsg("Hard Drive", $callback, $node);
|
||||
} elsif ($response_info->{'data'}->{BootSource} =~ /Network$/) {
|
||||
} elsif ($bootsource =~ /Network$/) {
|
||||
xCAT::SvrUtils::sendmsg("Network", $callback, $node);
|
||||
} elsif ($response_info->{'data'}->{BootSource} =~ /ExternalMedia$/) {
|
||||
} elsif ($bootsource =~ /ExternalMedia$/) {
|
||||
xCAT::SvrUtils::sendmsg("CD/DVD", $callback, $node);
|
||||
} elsif ($response_info->{'data'}->{BootSource} =~ /Default$/) {
|
||||
} elsif ($bootsource =~ /Default$/) {
|
||||
xCAT::SvrUtils::sendmsg("Default", $callback, $node);
|
||||
} else {
|
||||
my $error_msg = "Can not get valid rsetboot status, the data is " . $response_info->{'data'}->{BootSource};
|
||||
@ -1525,29 +1688,40 @@ sub reventlog_response {
|
||||
} else {
|
||||
my ($entry_string, $option_s) = split(",", $status_info{REVENTLOG_RESPONSE}{argv});
|
||||
my $content_info;
|
||||
my %output_s = () if ($option_s);
|
||||
my %output = ();
|
||||
my $entry_num = 0;
|
||||
$entry_string = "all" if ($entry_string eq "0");
|
||||
$entry_num = 0 + $entry_string if ($entry_string ne "all");
|
||||
|
||||
foreach my $key_url (keys %{$response_info->{data}}) {
|
||||
my %content = %{ ${ $response_info->{data} }{$key_url} };
|
||||
my $timestamp = $content{Timestamp};
|
||||
my $id_num = 0 + $content{Id} if ($content{Id});
|
||||
if (($entry_string eq "all" or ($id_num and ($entry_num ge $id_num))) and $content{Message}) {
|
||||
my $content_info = $content{Timestamp} . " " . $content{Message};
|
||||
if ($option_s) {
|
||||
$output_s{$id_num} = $content_info;
|
||||
$entry_num = $id_num if ($entry_num < $id_num);
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("$content_info", $callback, $node);
|
||||
}
|
||||
if ($content{Message}) {
|
||||
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($content{Timestamp}/1000);
|
||||
$mon += 1;
|
||||
$year += 1900;
|
||||
my $UTC_time = sprintf ("%02d/%02d/%04d %02d:%02d:%02d", $mon, $mday, $year, $hour, $min, $sec);
|
||||
my $content_info = $UTC_time . " [$content{Id}] " . $content{Message};
|
||||
$output{$timestamp} = $content_info;
|
||||
}
|
||||
}
|
||||
|
||||
if (%output_s) {
|
||||
for (my $key = $entry_num; $key >= 1; $key--) {
|
||||
xCAT::SvrUtils::sendmsg("$output_s{$key}", $callback, $node) if ($output_s{$key});
|
||||
}
|
||||
my $count = 0;
|
||||
if ($option_s) {
|
||||
xCAT::SvrUtils::sendmsg("$::NO_ATTRIBUTES_RETURNED", $callback, $node) if (!%output);
|
||||
foreach my $key ( sort { $b <=> $a } keys %output) {
|
||||
xCAT::MsgUtils->message("I", { data => ["$node: $output{$key}"] }, $callback) if ($output{$key});
|
||||
$count++;
|
||||
last if ($entry_string ne "all" and $count >= $entry_num);
|
||||
}
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("$::NO_ATTRIBUTES_RETURNED", $callback, $node) if (!%output);
|
||||
foreach my $key (sort keys %output) {
|
||||
xCAT::MsgUtils->message("I", { data => ["$node: $output{$key}"] }, $callback) if ($output{$key});
|
||||
$count++;
|
||||
last if ($entry_string ne "all" and $count >= $entry_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1582,6 +1756,7 @@ sub rspconfig_response {
|
||||
my $gateway = "n/a";
|
||||
my $prefix = "n/a";
|
||||
my $vlan = "n/a";
|
||||
my $hostname = "";
|
||||
my $default_gateway = "n/a";
|
||||
my $adapter_id = "n/a";
|
||||
my $error;
|
||||
@ -1595,6 +1770,9 @@ sub rspconfig_response {
|
||||
if (defined($content{DefaultGateway}) and $content{DefaultGateway}) {
|
||||
$default_gateway = $content{DefaultGateway};
|
||||
}
|
||||
if (defined($content{HostName}) and $content{HostName}) {
|
||||
$hostname = $content{HostName};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1640,11 +1818,25 @@ sub rspconfig_response {
|
||||
if ($grep_string =~ "vlan") {
|
||||
push @output, "BMC VLAN ID enabled: $vlan";
|
||||
}
|
||||
if ($grep_string =~ "hostname") {
|
||||
push @output, "BMC Hostname: $hostname";
|
||||
}
|
||||
}
|
||||
|
||||
xCAT::SvrUtils::sendmsg("$_", $callback, $node) foreach (@output);
|
||||
}
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RSPCONFIG_SET_RESPONSE") {
|
||||
if ($response_info->{'message'} eq $::RESPONSE_OK) {
|
||||
xCAT::SvrUtils::sendmsg("BMC Setting Hostname...", $callback, $node);
|
||||
}
|
||||
}
|
||||
if ($node_info{$node}{cur_status} eq "RSPCONFIG_DHCP_RESPONSE") {
|
||||
if ($response_info->{'message'} eq $::RESPONSE_OK) {
|
||||
xCAT::SvrUtils::sendmsg("BMC Setting IP to DHCP...", $callback, $node);
|
||||
}
|
||||
}
|
||||
|
||||
if ($next_status{ $node_info{$node}{cur_status} }) {
|
||||
$node_info{$node}{cur_status} = $next_status{ $node_info{$node}{cur_status} };
|
||||
gen_send_request($node);
|
||||
@ -1692,6 +1884,15 @@ sub rspconfig_sshcfg_response {
|
||||
if (@$output[0] == 1) {
|
||||
xCAT::SvrUtils::sendmsg("Error copying ssh keys to $bmcip:\n" . @$output[1], $callback, $node);
|
||||
}
|
||||
# For unknown reason, "echo" command above can fail (1 in 5), but return code 0 still returned.
|
||||
# There is nothing we can do but to just test if authorized_keys file was not created
|
||||
# and ask the user to rerun the command
|
||||
my $file_test_output = xCAT::RShellAPI::run_remote_shell_api($bmcip, $userid, $userpw, 0, 0, "[ ! -f ~/.ssh/authorized_keys ] && uptime");
|
||||
if (@$file_test_output[1] =~ "load average") {
|
||||
# If file was not there, we run "uptime" command and then look for "load average" in the output.
|
||||
# If file was there, "uptime" command is not executed
|
||||
xCAT::SvrUtils::sendmsg("Error copying ssh keys to $bmcip Rerun rspconfig command.", $callback, $node);
|
||||
}
|
||||
else {
|
||||
xCAT::SvrUtils::sendmsg("ssh keys copied to $bmcip", $callback, $node);
|
||||
}
|
||||
@ -1725,9 +1926,6 @@ sub rvitals_response {
|
||||
my $src;
|
||||
my $content_info;
|
||||
my @sorted_output;
|
||||
|
||||
xCAT::SvrUtils::sendmsg("$flag_debug Processing command: rvitals $grep_string", $callback, $node) if ($xcatdebugmode);
|
||||
print Dumper(%{$response_info->{data}});
|
||||
|
||||
foreach my $key_url (keys %{$response_info->{data}}) {
|
||||
my %content = %{ ${ $response_info->{data} }{$key_url} };
|
||||
@ -1809,8 +2007,6 @@ sub rflash_response {
|
||||
|
||||
my $response_info = decode_json $response->content;
|
||||
|
||||
print Dumper(%{$response_info->{data}});
|
||||
|
||||
my $update_id;
|
||||
my $update_activation = "Unknown";
|
||||
my $update_purpose;
|
||||
@ -1829,6 +2025,10 @@ sub rflash_response {
|
||||
if (defined($content{Version}) and $content{Version}) {
|
||||
$update_version = $content{Version};
|
||||
}
|
||||
else {
|
||||
# Entry has no Version attribute, skip listing it
|
||||
next;
|
||||
}
|
||||
if (defined($content{Activation}) and $content{Activation}) {
|
||||
$update_activation = (split(/\./, $content{Activation}))[ -1 ];
|
||||
}
|
||||
@ -1860,18 +2060,19 @@ sub rflash_response {
|
||||
# curl commands
|
||||
my $curl_login_cmd = "curl -c cjar -k -H 'Content-Type: application/json' -X POST $request_url/login -d '" . $content_login . "'";
|
||||
my $curl_logout_cmd = "curl -b cjar -k -H 'Content-Type: application/json' -X POST $request_url/logout -d '" . $content_logout . "'";
|
||||
my $curl_upload_cmd = "curl -b cjar -k -H 'Content-Type: application/octet-stream' -X PUT -T $::UPLOAD_FILE $request_url/upload/image/";
|
||||
my $curl_upload_cmd = "curl -b cjar -k -H 'Content-Type: application/octet-stream' -X PUT -T " . $::UPLOAD_FILE . " $request_url/upload/image/";
|
||||
|
||||
# Try to login
|
||||
my $curl_login_result = `$curl_login_cmd`;
|
||||
my $h = from_json($curl_login_result); # convert command output to hash
|
||||
if ($h->{message} eq $::RESPONSE_OK) {
|
||||
# Login successfull, upload the file
|
||||
xCAT::SvrUtils::sendmsg("Uploading $::UPLOAD_FILE ...", $callback, $node);
|
||||
my $curl_upload_result = `$curl_upload_cmd`;
|
||||
$h = from_json($curl_upload_result); # convert command output to hash
|
||||
if ($h->{message} eq $::RESPONSE_OK) {
|
||||
# Upload successfull
|
||||
xCAT::SvrUtils::sendmsg("Update file $::UPLOAD_FILE successfully uploaded", $callback, $node);
|
||||
xCAT::SvrUtils::sendmsg("Successful, use -l option to list.", $callback, $node);
|
||||
# Try to logoff, no need to check result, as there is nothing else to do if failure
|
||||
my $curl_logout_result = `$curl_logout_cmd`;
|
||||
}
|
||||
@ -1921,7 +2122,7 @@ sub rflash_response {
|
||||
}
|
||||
else {
|
||||
# Activation state of active and priority of non 0 - need to just set priority to 0 to activate
|
||||
print "Update is already active, just need to set priority to 0";
|
||||
print "Update is already active, just need to set priority to 0\n";
|
||||
$next_status{ $node_info{$node}{cur_status} } = "RFLASH_SET_PRIORITY_REQUEST";
|
||||
}
|
||||
}
|
||||
@ -1936,6 +2137,45 @@ sub rflash_response {
|
||||
|
||||
}
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RFLASH_UPDATE_CHECK_ID_RESPONSE") {
|
||||
my $activation_state;
|
||||
my $progress_state;
|
||||
my $priority_state;
|
||||
|
||||
# Look through all the software entries and find the id of the one that matches
|
||||
# the version of the uploaded file. Once found, set up request/response hash entries
|
||||
# to activate that image.
|
||||
foreach my $key_url (keys %{$response_info->{data}}) {
|
||||
my %content = %{ ${ $response_info->{data} }{$key_url} };
|
||||
|
||||
$update_id = (split(/\//, $key_url))[ -1 ];
|
||||
if (defined($content{Version}) and $content{Version}) {
|
||||
$update_version = $content{Version};
|
||||
if ($update_version eq $::UPLOAD_FILE_VERSION) {
|
||||
# Found a match of uploaded file version with the image in software/enumerate
|
||||
|
||||
# Set the image id for the activation request
|
||||
$status_info{RFLASH_UPDATE_ACTIVATE_REQUEST}{init_url} =
|
||||
$::SOFTWARE_URL . "/$update_id/attr/RequestedActivation";
|
||||
$status_info{RFLASH_UPDATE_CHECK_STATE_REQUEST}{init_url} =
|
||||
$::SOFTWARE_URL . "/$update_id";
|
||||
$status_info{RFLASH_SET_PRIORITY_REQUEST}{init_url} =
|
||||
$::SOFTWARE_URL . "/$update_id/attr/Priority";
|
||||
|
||||
# Set next steps to activate the image
|
||||
$next_status{ $node_info{$node}{cur_status} } = "RFLASH_UPDATE_ACTIVATE_REQUEST";
|
||||
$next_status{"RFLASH_UPDATE_ACTIVATE_REQUEST"} = "RFLASH_UPDATE_ACTIVATE_RESPONSE";
|
||||
$next_status{"RFLASH_UPDATE_ACTIVATE_RESPONSE"} = "RFLASH_UPDATE_CHECK_STATE_REQUEST";
|
||||
$next_status{"RFLASH_UPDATE_CHECK_STATE_REQUEST"} = "RFLASH_UPDATE_CHECK_STATE_RESPONSE";
|
||||
|
||||
$next_status{"RFLASH_SET_PRIORITY_REQUEST"} = "RFLASH_SET_PRIORITY_RESPONSE";
|
||||
$next_status{"RFLASH_SET_PRIORITY_RESPONSE"} = "RFLASH_UPDATE_CHECK_STATE_REQUEST";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($node_info{$node}{cur_status} eq "RFLASH_DELETE_IMAGE_RESPONSE") {
|
||||
xCAT::SvrUtils::sendmsg("Firmware update successfully removed", $callback, $node);
|
||||
}
|
||||
|
@ -484,7 +484,7 @@ sub process_request {
|
||||
unlink glob("$destdir/rootimg.*");
|
||||
|
||||
if ($method =~ /cpio/) {
|
||||
if (!$exlistloc) {
|
||||
if (!$excludestr) {
|
||||
$excludestr = "find . -xdev -print0 | cpio -H newc -o -0 | $compress -c - > ../rootimg.$suffix";
|
||||
} else {
|
||||
chdir("$rootimg_dir");
|
||||
@ -505,7 +505,7 @@ sub process_request {
|
||||
if ($checkoption2 !~ /unrecognized/) {
|
||||
$option .= "--selinux ";
|
||||
}
|
||||
if (!$exlistloc) {
|
||||
if (!$excludestr) {
|
||||
$excludestr = "find . -xdev -print0 | tar $option --no-recursion --use-compress-program=$compress --null -T - -cf ../rootimg.$suffix";
|
||||
} else {
|
||||
chdir("$rootimg_dir");
|
||||
@ -526,7 +526,6 @@ sub process_request {
|
||||
}
|
||||
$excludestr = "cat $xcat_packimg_tmpfile|cpio -dump $temppath";
|
||||
}
|
||||
|
||||
chdir("$rootimg_dir");
|
||||
my $outputmsg = `$excludestr 2>&1`;
|
||||
unless($?){
|
||||
|
@ -7,6 +7,7 @@
|
||||
Supported command:
|
||||
rpower
|
||||
rinv
|
||||
rvitals
|
||||
|
||||
=cut
|
||||
|
||||
@ -63,6 +64,7 @@ sub handled_commands
|
||||
return {
|
||||
rpower => ["nodehm:mgt","pduoutlet:pdu=\.\*"],
|
||||
rinv => ["nodehm:mgt"],
|
||||
rvitals => ["nodehm:mgt"],
|
||||
nodeset => ["nodehm:mgt"],
|
||||
rspconfig => ["nodehm:mgt"],
|
||||
pdudiscover => "pdu",
|
||||
@ -138,11 +140,13 @@ sub process_request
|
||||
#fill in the total outlet count for each pdu
|
||||
$pdutab = xCAT::Table->new('pdu');
|
||||
@pduents = $pdutab->getAllNodeAttribs(['node', 'outlet']);
|
||||
fill_outletCount(\@pduents, $callback);
|
||||
#fill_outletCount(\@pduents, $callback);
|
||||
|
||||
if( $command eq "rinv") {
|
||||
#for higher performance, handle node in batch
|
||||
return powerstat($noderange, $callback);
|
||||
return showMFR($noderange, $callback);
|
||||
}elsif ($command eq "rvitals") {
|
||||
return showMonitorData($noderange, $callback);
|
||||
}elsif ($command eq "rpower") {
|
||||
my $subcmd = $exargs[0];
|
||||
if (($subcmd eq 'pduoff') || ($subcmd eq 'pduon') || ($subcmd eq 'pdustat')|| ($subcmd eq 'pdureset') ){
|
||||
@ -177,6 +181,8 @@ sub process_request
|
||||
my $subcmd = $exargs[0];
|
||||
if ($subcmd eq 'sshcfg') {
|
||||
process_sshcfg($noderange, $subcmd, $callback);
|
||||
}elsif ($subcmd =~ /ip|netmask|hostname/) {
|
||||
process_netcfg($request, $subreq, $subcmd, $callback);
|
||||
} else {
|
||||
$callback->({ errorcode => [1],error => "The input $command $subcmd is not support for pdu"});
|
||||
}
|
||||
@ -467,14 +473,130 @@ sub connectTopdu {
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 process_netcfg
|
||||
|
||||
Config hostname of PDU
|
||||
Config ip/netmask of PDU via PduManager command
|
||||
PduManager is a tool for CoralPdu to manager the PDU.
|
||||
* /dev/shm/bin/PduManager -h
|
||||
'-i' set PDU system IP
|
||||
'-n' set system ip netmask. e.g.:PduManager -i xxx.xxx.xxx.xxx -n xxx.xxx.xxx.xxx
|
||||
|
||||
example: rspconfig coralpdu hostname=coralpdu
|
||||
rspconfig coralpdu ip=1.1.1.1 netmask=255.0.0.0
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub process_netcfg {
|
||||
my $request = shift;
|
||||
my $subreq = shift;
|
||||
my $subcmd = shift;
|
||||
my $callback = shift;
|
||||
my $hostname;
|
||||
my $ip;
|
||||
my $netmask;
|
||||
my $args;
|
||||
my $exp;
|
||||
my $errstr;
|
||||
|
||||
my $extrargs = $request->{arg};
|
||||
my @exargs = ($request->{arg});
|
||||
if (ref($extrargs)) {
|
||||
@exargs = @$extrargs;
|
||||
}
|
||||
|
||||
my $nodes = $request->{node};
|
||||
my $node_number = @$nodes;
|
||||
if ($node_number gt "1") {
|
||||
xCAT::SvrUtils::sendmsg("Can not configure more than 1 nodes", $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
my $pdu = @$nodes[0];
|
||||
my $rsp = {};
|
||||
|
||||
my $nodetab = xCAT::Table->new('hosts');
|
||||
my $nodehash = $nodetab->getNodesAttribs($nodes,['ip','otherinterfaces']);
|
||||
|
||||
# connect to PDU
|
||||
my $static_ip = $nodehash->{$pdu}->[0]->{ip};
|
||||
my $discover_ip = $nodehash->{$pdu}->[0]->{otherinterfaces};
|
||||
($exp, $errstr) = session_connect($static_ip, $discover_ip);
|
||||
if (defined $errstr) {
|
||||
xCAT::SvrUtils::sendmsg("Failed to connect", $callback);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach my $cmd (@exargs) {
|
||||
my ($key, $value) = split(/=/, $cmd);
|
||||
if ($key =~ /hostname/) {
|
||||
$hostname = $value;
|
||||
my ($ret, $err) = session_exec($exp, "echo $hostname > /etc/hostname;/etc/init.d/hostname.sh");
|
||||
if (defined $err) {
|
||||
xCAT::SvrUtils::sendmsg("Failed to set hostname", $callback);
|
||||
}
|
||||
}elsif ($key =~ /ip/) {
|
||||
$ip = $value;
|
||||
} elsif ($key =~ /netmask/) {
|
||||
$netmask = $value;
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("rspconfig $cmd is not support yet, ignored", $callback);
|
||||
}
|
||||
}
|
||||
|
||||
$args = "/dev/shm/bin/PduManager ";
|
||||
my $opt;
|
||||
if ($ip) {
|
||||
$opt = "-i $ip ";
|
||||
}
|
||||
if ($netmask) {
|
||||
$opt = $opt . "-n $netmask";
|
||||
}
|
||||
if ($opt) {
|
||||
my $dshcmd = $args . $opt ;
|
||||
my ($ret, $err) = session_exec($exp, $dshcmd);
|
||||
if (defined $err) {
|
||||
#session will be hung if ip address changed
|
||||
my $p = Net::Ping->new();
|
||||
if ( ($p->ping($ip)) && ($err =~ /TIMEOUT/) ) {
|
||||
xCAT::SvrUtils::sendmsg("$ip is reachable", $callback);
|
||||
} else {
|
||||
xCAT::SvrUtils::sendmsg("Failed to run $dshcmd, error=$err", $callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
xCAT::SvrUtils::sendmsg("$dshcmd ran successfully", $callback);
|
||||
xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$pdu,"ip=$ip","otherinterfaces="] }, $subreq, 0, 1);
|
||||
xCAT::Utils->runxcmd({ command => ['makehosts'], node => [$pdu] }, $subreq, 0, 1);
|
||||
}
|
||||
if (defined $exp) {
|
||||
$exp->hard_close();
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 process_sshcfg
|
||||
|
||||
Config passwordless for coralpdu
|
||||
|
||||
example: rspconfig coralpdu sshcfg
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub process_sshcfg {
|
||||
my $noderange = shift;
|
||||
my $subcmd = shift;
|
||||
my $callback = shift;
|
||||
|
||||
#this is default password for CoralPDU
|
||||
my $password = "password8";
|
||||
my $userid = "root";
|
||||
my $timeout = 10;
|
||||
my $timeout = 30;
|
||||
my $keyfile = "/root/.ssh/id_rsa.pub";
|
||||
my $rootkey = `cat /root/.ssh/id_rsa.pub`;
|
||||
my $cmd;
|
||||
@ -492,20 +614,7 @@ sub process_sshcfg {
|
||||
|
||||
my $static_ip = $nodehash->{$pdu}->[0]->{ip};
|
||||
my $discover_ip = $nodehash->{$pdu}->[0]->{otherinterfaces};
|
||||
my $ssh_ip;
|
||||
|
||||
my $p = Net::Ping->new();
|
||||
if ($p->ping($static_ip)) {
|
||||
$ssh_ip = $static_ip;
|
||||
} elsif ($p->ping($discover_ip)) {
|
||||
$ssh_ip = $discover_ip;
|
||||
} else {
|
||||
$msg = " is not reachable";
|
||||
xCAT::SvrUtils::sendmsg($msg, $callback, $pdu, %allerrornodes);
|
||||
next;
|
||||
}
|
||||
|
||||
my ($exp, $errstr) = session_connect($ssh_ip, $userid, $password, $timeout);
|
||||
my ($exp, $errstr) = session_connect($static_ip, $discover_ip);
|
||||
if (!defined $exp) {
|
||||
$msg = " Failed to connect $errstr";
|
||||
xCAT::SvrUtils::sendmsg($msg, $callback, $pdu, %allerrornodes);
|
||||
@ -519,10 +628,6 @@ sub process_sshcfg {
|
||||
($ret, $err) = session_exec($exp, "chmod 700 /home/root/.ssh");
|
||||
($ret, $err) = session_exec($exp, "echo \"$rootkey\" >/home/root/.ssh/authorized_keys");
|
||||
($ret, $err) = session_exec($exp, "chmod 644 /home/root/.ssh/authorized_keys");
|
||||
#config dhcp ip address to static
|
||||
if ($ssh_ip eq $discover_ip) {
|
||||
# ($ret, $err) = session_exec($exp, "ifconfig eth0 $static_ip");
|
||||
}
|
||||
|
||||
$exp->hard_close();
|
||||
}
|
||||
@ -531,14 +636,27 @@ sub process_sshcfg {
|
||||
}
|
||||
|
||||
sub session_connect {
|
||||
my $server = shift;
|
||||
my $userid = shift;
|
||||
my $password = shift;
|
||||
my $timeout = shift;
|
||||
my $static_ip = shift;
|
||||
my $discover_ip = shift;
|
||||
|
||||
my $ssh = Expect->new;
|
||||
my $command = 'ssh';
|
||||
my @parameters = ($userid . "@" . $server);
|
||||
#default password for coral pdu
|
||||
my $password = "password8";
|
||||
my $userid = "root";
|
||||
my $timeout = 30;
|
||||
|
||||
my $ssh_ip;
|
||||
my $p = Net::Ping->new();
|
||||
if ($p->ping($static_ip)) {
|
||||
$ssh_ip = $static_ip;
|
||||
} elsif ($p->ping($discover_ip)) {
|
||||
$ssh_ip = $discover_ip;
|
||||
} else {
|
||||
return(undef, " is not reachable\n");
|
||||
}
|
||||
|
||||
my $ssh = Expect->new;
|
||||
my $command = 'ssh';
|
||||
my @parameters = ($userid . "@" . $ssh_ip);
|
||||
|
||||
$ssh->debug(0);
|
||||
$ssh->log_stdout(0); # suppress stdout output..
|
||||
@ -571,7 +689,7 @@ sub session_exec {
|
||||
my $timeout = shift;
|
||||
my $prompt = shift;
|
||||
|
||||
$timeout = 10 unless defined $timeout;
|
||||
$timeout = 30 unless defined $timeout;
|
||||
$prompt = qr/.*#/ unless defined $prompt;
|
||||
|
||||
|
||||
@ -585,6 +703,18 @@ sub session_exec {
|
||||
return($mbmatch);
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
=head3 process_pdudiscover
|
||||
|
||||
Discover the pdu for a given range of DHCP ip address
|
||||
it will call switchdiscover command with -s snmp --pdu options
|
||||
|
||||
example: pdudiscover --range iprange -w
|
||||
|
||||
=cut
|
||||
|
||||
#------------------------------------------------------------------
|
||||
sub process_pdudiscover {
|
||||
my $request = shift;
|
||||
my $sub_req = shift;
|
||||
@ -615,10 +745,96 @@ sub process_pdudiscover {
|
||||
my $rsp = {};
|
||||
push @{ $rsp->{data} }, "$result";
|
||||
xCAT::MsgUtils->message("I", $rsp, $callback);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 showMFR
|
||||
|
||||
show MFR information of PDU via PduManager command
|
||||
PduManager is a tool for CoralPdu to manager the PDU.
|
||||
* /dev/shm/bin/PduManager -h
|
||||
'-m' show MFR info
|
||||
|
||||
example: rinv coralpdu
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
sub showMFR {
|
||||
my $noderange = shift;
|
||||
my $callback = shift;
|
||||
my $output;
|
||||
|
||||
my $nodetab = xCAT::Table->new('hosts');
|
||||
my $nodehash = $nodetab->getNodesAttribs($noderange,['ip','otherinterfaces']);
|
||||
|
||||
foreach my $pdu (@$noderange) {
|
||||
# connect to PDU
|
||||
my $static_ip = $nodehash->{$pdu}->[0]->{ip};
|
||||
my $discover_ip = $nodehash->{$pdu}->[0]->{otherinterfaces};
|
||||
my ($exp, $errstr) = session_connect($static_ip, $discover_ip);
|
||||
if (defined $errstr) {
|
||||
xCAT::SvrUtils::sendmsg("Failed to connect: $errstr", $callback);
|
||||
}
|
||||
|
||||
my ($ret, $err) = session_exec($exp, "/dev/shm/bin/PduManager -m");
|
||||
if (defined $err) {
|
||||
xCAT::SvrUtils::sendmsg("Failed to list MFR information: $err", $callback);
|
||||
}
|
||||
if (defined $ret) {
|
||||
xCAT::SvrUtils::sendmsg("$ret", $callback);
|
||||
}
|
||||
|
||||
$exp->hard_close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
=head3 showMonitorData
|
||||
|
||||
Show realtime monitor data(input voltage, current, power)
|
||||
of PDU via PduManager command
|
||||
PduManager is a tool for CoralPdu to manager the PDU.
|
||||
* /dev/shm/bin/PduManager -h
|
||||
'-d' show realtime monitor data(input voltage, current, power)
|
||||
|
||||
example: rvitals coralpdu
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------
|
||||
sub showMonitorData {
|
||||
my $noderange = shift;
|
||||
my $callback = shift;
|
||||
my $output;
|
||||
|
||||
my $nodetab = xCAT::Table->new('hosts');
|
||||
my $nodehash = $nodetab->getNodesAttribs($noderange,['ip','otherinterfaces']);
|
||||
|
||||
foreach my $pdu (@$noderange) {
|
||||
# connect to PDU
|
||||
my $static_ip = $nodehash->{$pdu}->[0]->{ip};
|
||||
my $discover_ip = $nodehash->{$pdu}->[0]->{otherinterfaces};
|
||||
my ($exp, $errstr) = session_connect($static_ip, $discover_ip);
|
||||
|
||||
my $ret;
|
||||
my $err;
|
||||
|
||||
($ret, $err) = session_exec($exp, "/dev/shm/bin/PduManager -d");
|
||||
if (defined $err) {
|
||||
xCAT::SvrUtils::sendmsg("Failed to show monitor data: $err", $callback);
|
||||
}
|
||||
if (defined $ret) {
|
||||
xCAT::SvrUtils::sendmsg("$ret", $callback,$pdu);
|
||||
}
|
||||
|
||||
$exp->hard_close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
@ -390,8 +390,7 @@ sub preprocess_request {
|
||||
if ($ntab) {
|
||||
foreach (@{ $ntab->getAllEntries() }) {
|
||||
next unless ($_->{dynamicrange});
|
||||
# if dynamicrange specified but dhcpserver was not - issue error message
|
||||
push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver})
|
||||
push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver} && xCAT::NetworkUtils->nodeonmynet($_->{dhcpserver}));
|
||||
}
|
||||
}
|
||||
return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash, \@dhcpsvrs);
|
||||
@ -645,7 +644,7 @@ sub process_request {
|
||||
}
|
||||
|
||||
#Don't bother to try dhcp binding changes if sub_req not passed, i.e. service node build time
|
||||
unless (($inittime) || ($args[0] eq 'offline')) {
|
||||
unless ($inittime) {
|
||||
|
||||
#dhcp stuff
|
||||
my $do_dhcpsetup = 1;
|
||||
@ -654,9 +653,11 @@ sub process_request {
|
||||
if (defined($t_entry)) {
|
||||
if ($t_entry =~ /0|n|N/) { $do_dhcpsetup = 0; }
|
||||
}
|
||||
if ($do_dhcpsetup) {
|
||||
# For offline operation, remove the dhcp entries whatever dhcpset is disabled in site ( existing code logic, just keep it as is)
|
||||
if ($do_dhcpsetup || $args[0] eq 'offline') {
|
||||
my @parameter;
|
||||
push @parameter, '-l' if ($::request->{'_disparatetftp'}->[0]);
|
||||
push @parameter, '-l' if ($request->{'_disparatetftp'}->[0]);
|
||||
push @parameter, '-d' if ($args[0] eq 'offline');
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "petitboot: issue makedhcp request");
|
||||
|
||||
$sub_req->({ command => ['makedhcp'],
|
||||
@ -668,12 +669,6 @@ sub process_request {
|
||||
|
||||
}
|
||||
|
||||
if ($args[0] eq 'offline') {
|
||||
|
||||
# If nodeset directive was offline we need to remove dhcp entries
|
||||
$sub_req->({ command => ['makedhcp'], arg => ['-d'], node => \@normalnodeset }, $callback);
|
||||
}
|
||||
|
||||
#now run the end part of the prescripts
|
||||
unless ($args[0] eq '') { # or $args[0] eq 'enact')
|
||||
$errored = 0;
|
||||
|
@ -166,6 +166,14 @@ sub rinstall {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if($command eq "rinstall" and scalar(@nodes) > 1 and $CONSOLE){
|
||||
my $rsp;
|
||||
$rsp->{errorcode}->[0]=1;
|
||||
$rsp->{error}->[0]="rinstall -c/--console can only be run against one node! Please use winstall -c/--console for multiple nodes.";
|
||||
xCAT::MsgUtils->message("E",$rsp,$callback);
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $rc = 0;
|
||||
my @parameter;
|
||||
|
||||
@ -540,11 +548,6 @@ sub rinstall {
|
||||
arg => \@rpowerarg
|
||||
);
|
||||
|
||||
#TODO: When OPENBMC support is finished, this line should be removed
|
||||
if($hmkey =~ /^openbmc$/){
|
||||
$req{environment}{XCAT_OPENBMC_DEVEL} = "YES";
|
||||
}
|
||||
|
||||
my $res =
|
||||
xCAT::Utils->runxcmd(
|
||||
\%req,
|
||||
|
@ -132,25 +132,25 @@ sub findme {
|
||||
}
|
||||
}
|
||||
my $bmc_node = undef;
|
||||
my @bmc_nodes = ();
|
||||
if ($request->{'mtm'}->[0] and $request->{'serial'}->[0]) {
|
||||
my $mtms = $request->{'mtm'}->[0] . "*" . $request->{'serial'}->[0];
|
||||
my $tmp_nodes = $::XCATVPDHASH{$mtms};
|
||||
foreach (@$tmp_nodes) {
|
||||
if ($::XCATMPHASH{$_}) {
|
||||
$bmc_node = $_;
|
||||
push @bmc_nodes, $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unless ($bmc_node) {
|
||||
if ($request->{'bmcmac'}->[0]) {
|
||||
my $bmcmac = lc($request->{'bmcmac'}->[0]);
|
||||
$bmcmac =~ s/\://g;
|
||||
my $tmp_node = "node-$bmcmac";
|
||||
$bmc_node = $tmp_node if ($::XCATMPHASH{$tmp_node});
|
||||
}
|
||||
if ($request->{'bmcmac'}->[0]) {
|
||||
my $bmcmac = lc($request->{'bmcmac'}->[0]);
|
||||
$bmcmac =~ s/\://g;
|
||||
my $tmp_node = "node-$bmcmac";
|
||||
push @bmc_nodes, $tmp_node if ($::XCATMPHASH{$tmp_node});
|
||||
}
|
||||
|
||||
$bmc_node = join(",", @bmc_nodes);
|
||||
if ($node) {
|
||||
my $skiphostip;
|
||||
my $skipbmcip;
|
||||
@ -827,7 +827,7 @@ Usage:
|
||||
Common:
|
||||
nodediscoverls
|
||||
nodediscoverls [-h|--help|-v|--version]
|
||||
nodediscoverls [-t seq|profile|switch|blade|manual|undef|zvm|all] [-l]
|
||||
nodediscoverls [-t seq|profile|switch|blade|manual|mtms|undef|zvm|all] [-l]
|
||||
nodediscoverls [-u uuid] [-l]
|
||||
z/VM:
|
||||
nodediscoverls [-t zvm][-z|--zvmhost <noderange>] [-l]";
|
||||
@ -864,7 +864,7 @@ Usage:
|
||||
# If the type is specified, display the corresponding type of nodes
|
||||
my ( @SEQDiscover, @ZVMDiscover );
|
||||
if ($type) {
|
||||
if ($type !~ /^(seq|profile|switch|blade|manual|undef|zvm|all)$/) {
|
||||
if ($type !~ /^(seq|profile|switch|blade|manual|mtms|undef|zvm|all)$/) {
|
||||
$usage->($callback, "The discovery type \'$type\' is not supported.");
|
||||
return;
|
||||
}
|
||||
@ -945,7 +945,7 @@ Usage:
|
||||
} else {
|
||||
$ent->{'node'} = 'undef' unless ($ent->{'node'});
|
||||
$ent->{'method'} = 'undef' unless ($ent->{'method'});
|
||||
push @discoverednodes, sprintf(" %-40s%-20s%-15s%-10s%-20s", $ent->{'uuid'}, $ent->{'node'}, $ent->{'method'}, $ent->{'mtm'}, substr($ent->{'serial'}, 0, 19));
|
||||
push @discoverednodes, sprintf(" %-40s%-20s%-15s%-10s %-20s", $ent->{'uuid'}, $ent->{'node'}, $ent->{'method'}, $ent->{'mtm'}, substr($ent->{'serial'}, 0, 19));
|
||||
}
|
||||
}
|
||||
|
||||
@ -956,7 +956,7 @@ Usage:
|
||||
}
|
||||
if (@discoverednodes) {
|
||||
unless ($long) {
|
||||
push @{ $rsp->{data} }, sprintf(" %-40s%-20s%-15s%-10s%-13s", 'UUID', 'NODE', 'METHOD', 'MTM', 'SERIAL');
|
||||
push @{ $rsp->{data} }, sprintf(" %-40s%-20s%-15s%-10s %-20s", 'UUID', 'NODE', 'METHOD', 'MTM', 'SERIAL');
|
||||
}
|
||||
foreach (@discoverednodes) {
|
||||
push @{ $rsp->{data} }, "$_";
|
||||
|
@ -100,6 +100,8 @@ sub mknetboot
|
||||
$nodestatus = $t_entry;
|
||||
}
|
||||
|
||||
my @myself = xCAT::NetworkUtils->determinehostname();
|
||||
my $myname = $myself[ (scalar @myself) - 1 ];
|
||||
#}
|
||||
|
||||
my $ntents = $ostab->getNodesAttribs($req->{node}, [ 'os', 'arch', 'profile', 'provmethod' ]);
|
||||
@ -333,7 +335,7 @@ sub mknetboot
|
||||
if ($statelite) {
|
||||
unless (-r "$rootimgdir/kernel") {
|
||||
$callback->({
|
||||
error => [qq{Did you run "genimage" before running "liteimg"? kernel cannot be found}],
|
||||
error => [qq{Did you run "genimage" before running "liteimg"? kernel cannot be found at $rootimgdir/kernel on $myname}],
|
||||
errorcode => [1]
|
||||
});
|
||||
next;
|
||||
@ -362,7 +364,7 @@ sub mknetboot
|
||||
} else {
|
||||
unless (-r "$rootimgdir/kernel") {
|
||||
$callback->({
|
||||
error => [qq{Did you run "genimage" before running "packimage"? kernel cannot be found}],
|
||||
error => [qq{Did you run "genimage" before running "packimage"? kernel cannot be found at $rootimgdir/kernel on $myname}],
|
||||
errorcode => [1]
|
||||
});
|
||||
next;
|
||||
|
@ -251,7 +251,7 @@ sub process_request {
|
||||
$cb->({ node => [ { name => $switch, data => ["PASS"] } ] });
|
||||
next;
|
||||
}
|
||||
foreach my $port (sort keys %{ $macinfo->{$switch} }) {
|
||||
foreach my $port (map{$_->[0]}sort{$a->[1] cmp $b->[1] || $a->[2] <=> $b->[2]}map{[$_, /^(.*?)(\d+)?$/]} keys %{ $macinfo->{$switch} }) {
|
||||
my $node = '';
|
||||
if (defined($macinfo->{$switch}->{$port}->{Node})) {
|
||||
$node = $macinfo->{$switch}->{$port}->{Node};
|
||||
@ -336,25 +336,25 @@ sub process_request {
|
||||
}
|
||||
}
|
||||
my $bmc_node = undef;
|
||||
my @bmc_nodes = ();
|
||||
if ($req->{'mtm'}->[0] and $req->{'serial'}->[0]) {
|
||||
my $mtms = $req->{'mtm'}->[0] . "*" . $req->{'serial'}->[0];
|
||||
my $tmp_nodes = $::XCATVPDHASH{$mtms};
|
||||
foreach (@$tmp_nodes) {
|
||||
if ($::XCATMPHASH{$_}) {
|
||||
$bmc_node = $_;
|
||||
push @bmc_nodes, $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unless ($bmc_node) {
|
||||
if ($req->{'bmcmac'}->[0]) {
|
||||
my $bmcmac = lc($req->{'bmcmac'}->[0]);
|
||||
$bmcmac =~ s/\://g;
|
||||
my $tmp_node = "node-$bmcmac";
|
||||
$bmc_node = $tmp_node if ($::XCATMPHASH{$tmp_node});
|
||||
}
|
||||
if ($req->{'bmcmac'}->[0]) {
|
||||
my $bmcmac = lc($req->{'bmcmac'}->[0]);
|
||||
$bmcmac =~ s/\://g;
|
||||
my $tmp_node = "node-$bmcmac";
|
||||
push @bmc_nodes, $tmp_node if ($::XCATMPHASH{$tmp_node});
|
||||
}
|
||||
|
||||
$bmc_node = join(",", @bmc_nodes);
|
||||
if ($node) {
|
||||
xCAT::MsgUtils->message("S", "xcat.discovery.switch: ($req->{_xcat_clientmac}->[0]) Found node: $node");
|
||||
|
||||
|
@ -21,6 +21,7 @@ no strict;
|
||||
use Data::Dumper;
|
||||
use Socket;
|
||||
use Expect;
|
||||
use SNMP;
|
||||
use xCAT::data::switchinfo;
|
||||
|
||||
#global variables for this module
|
||||
@ -144,7 +145,7 @@ sub parse_args {
|
||||
# Process command-line flags
|
||||
#############################################
|
||||
if (!GetOptions( \%opt,
|
||||
qw(h|help V|verbose v|version x z w r n range=s s=s setup pdu))) {
|
||||
qw(h|help V|verbose v|version x z w r n range=s s=s c=s setup pdu))) {
|
||||
return( usage() );
|
||||
}
|
||||
|
||||
@ -252,6 +253,13 @@ sub parse_args {
|
||||
$globalopt{n} = 1;
|
||||
}
|
||||
|
||||
#########################################################
|
||||
# Accept the community string from user
|
||||
#########################################################
|
||||
if ( exists( $opt{c} )) {
|
||||
$community=$opt{c};
|
||||
}
|
||||
|
||||
#########################################################
|
||||
# setup discover switch
|
||||
#########################################################
|
||||
@ -339,75 +347,33 @@ sub process_request {
|
||||
@scan_types = @{$globalopt{scan_types}};
|
||||
}
|
||||
|
||||
my $all_result;
|
||||
my %username_hash = ();
|
||||
$result = undef;
|
||||
foreach my $st (@scan_types) {
|
||||
no strict;
|
||||
my $fn = $global_scan_type{$st};
|
||||
my $tmp_result = &$fn(\%request, $callback);
|
||||
if (ref($tmp_result) eq 'HASH') {
|
||||
$all_result->{$st} = $tmp_result;
|
||||
}
|
||||
}
|
||||
|
||||
#consolidate the results by merging the swithes with the same ip or same mac
|
||||
#or same hostname
|
||||
my $result;
|
||||
my $merged;
|
||||
my $counter=0;
|
||||
foreach my $st (keys %$all_result) {
|
||||
my $tmp_result = $all_result->{$st};
|
||||
#send_msg( \%request, 1, Dumper($tmp_result));
|
||||
foreach my $old_mac (keys %$tmp_result) {
|
||||
$same = 0;
|
||||
foreach my $new_mac (keys %$result) {
|
||||
my $old_ip = $tmp_result->{$old_mac}->{ip};
|
||||
my $old_name = $tmp_result->{$old_mac}->{name};
|
||||
my $old_vendor = $tmp_result->{$old_mac}->{vendor};
|
||||
my $new_ip = $result->{$new_mac}->{ip};
|
||||
my $new_name = $result->{$new_mac}->{name};
|
||||
my $new_vendor = $result->{$new_mac}->{vendor};
|
||||
|
||||
if (($old_mac eq $new_mac) ||
|
||||
($old_ip && ($old_ip eq $new_ip)) ||
|
||||
($old_name && ($old_name eq $new_name))) {
|
||||
$same = 1;
|
||||
my $key =$new_mac;
|
||||
if ($new_mac =~ /nomac/) {
|
||||
if ($old_mac =~ /nomac/) {
|
||||
$key = "nomac_$counter";
|
||||
$counter++;
|
||||
} else {
|
||||
$key = $old_mac;
|
||||
}
|
||||
}
|
||||
if ($old_name) {
|
||||
$result->{$key}->{name} = $old_name;
|
||||
}
|
||||
if ($old_ip) {
|
||||
$result->{$key}->{ip} = $old_ip;
|
||||
}
|
||||
$result->{$key}->{vendor} = $new_vendor;
|
||||
if ($old_vendor) {
|
||||
if ($old_vendor ne $new_vendor) {
|
||||
$result->{$key}->{vendor} .= " " . $old_vendor;
|
||||
} else {
|
||||
$result->{$key}->{vendor} = $old_vendor;
|
||||
}
|
||||
}
|
||||
|
||||
if ($key ne $new_mac) {
|
||||
delete $result->{$new_mac};
|
||||
foreach (keys %$tmp_result) {
|
||||
$result->{$_} = $tmp_result->{$_};
|
||||
#appending mac address to end of hostname
|
||||
my $name = $result->{$_}->{name};
|
||||
if (exists $username_hash{$name}) {
|
||||
if ($name eq '') {
|
||||
$name = "$device";
|
||||
}
|
||||
my $mac_str = lc($_);
|
||||
$mac_str =~ s/\://g;
|
||||
$result->{$_}->{name} = "$name-$mac_str";
|
||||
} else {
|
||||
$username_hash{$name} = 1;
|
||||
}
|
||||
}
|
||||
if (!$same) {
|
||||
$result->{$old_mac} = $tmp_result->{$old_mac};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!($result)) {
|
||||
send_msg( \%request, 0, " No switch found ");
|
||||
send_msg( \%request, 0, " No $device found ");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -934,13 +900,6 @@ sub snmp_scan {
|
||||
}
|
||||
my @lines = split /\n/, $result;
|
||||
|
||||
#set community string for switch
|
||||
$community = "public";
|
||||
my @snmpcs = xCAT::TableUtils->get_site_attribute("snmpc");
|
||||
my $tmp = $snmpcs[0];
|
||||
if (defined($tmp)) { $community = $tmp }
|
||||
|
||||
|
||||
foreach my $line (@lines) {
|
||||
my @array = split / /, $line;
|
||||
if ($line =~ /\b(\d{1,3}(?:\.\d{1,3}){3})\b/)
|
||||
@ -996,20 +955,47 @@ sub get_snmpvendorinfo {
|
||||
my $request = shift;
|
||||
my $ip = shift;
|
||||
my $snmpwalk_vendor;
|
||||
my $result;
|
||||
my $rc=1;
|
||||
|
||||
#checking snmp connection
|
||||
#during discovery phase, xCAT will not know the community string for snmp
|
||||
#so, will try community string from following way:
|
||||
# 1) -c options from user input
|
||||
# 2) snmpc attribute defined in the site table
|
||||
# 3) default community string for the switches.
|
||||
|
||||
#Ubuntu only takes OID
|
||||
#get sysDescr.0";
|
||||
my $ccmd = "snmpwalk -Os -v1 -c $community $ip 1.3.6.1.2.1.1.1";
|
||||
if (exists($globalopt{verbose})) {
|
||||
send_msg($request, 0, "Process command: $ccmd\n");
|
||||
my @comm_list;
|
||||
my $snmpver = '1';
|
||||
|
||||
my @snmpcs = xCAT::TableUtils->get_site_attribute("snmpc");
|
||||
my $snmp_site = $snmpcs[0];
|
||||
|
||||
if ($community) {
|
||||
push @comm_list, $community;
|
||||
}
|
||||
if ($snmp_site) {
|
||||
push @comm_list, $snmp_site;
|
||||
}
|
||||
push @comm_list, 'public';
|
||||
|
||||
my $result = xCAT::Utils->runcmd($ccmd, 0);
|
||||
if ($::RUNCMD_RC != 0)
|
||||
{
|
||||
foreach $comms(@comm_list) {
|
||||
#get sysDescr.0";
|
||||
my $ccmd = "snmpwalk -Os -v1 -c $comms $ip 1.3.6.1.2.1.1.1";
|
||||
if (exists($globalopt{verbose})) {
|
||||
send_msg($request, 1, "Could not process this command: $ccmd" );
|
||||
send_msg($request, 0, "Process command: $ccmd\n");
|
||||
}
|
||||
$result = xCAT::Utils->runcmd($ccmd, 0);
|
||||
if ($::RUNCMD_RC == 0)
|
||||
{
|
||||
$community = $comms;
|
||||
$rc=0;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if ($rc == 1) {
|
||||
if (exists($globalopt{verbose})) {
|
||||
send_msg($request, 1, "Could not process snmpwalk command to get sysDescr, please verify community string" );
|
||||
}
|
||||
return $snmpwalk_vendor;
|
||||
}
|
||||
@ -1107,7 +1093,7 @@ sub get_snmphostname {
|
||||
my ($desc,$hostname) = split /: /, $result;
|
||||
|
||||
if (exists($globalopt{verbose})) {
|
||||
send_msg($request, 0, "switch hostname = $hostname\n" );
|
||||
send_msg($request, 0, "$device hostname = $hostname\n" );
|
||||
}
|
||||
|
||||
return $hostname;
|
||||
@ -1140,7 +1126,7 @@ sub get_hostname {
|
||||
if ( !$host ) {
|
||||
my $ip_str = $ip;
|
||||
$ip_str =~ s/\./\-/g;
|
||||
$host = "switch-$ip_str";
|
||||
$host = "$device-$ip_str";
|
||||
}
|
||||
}
|
||||
return $host;
|
||||
@ -1404,15 +1390,18 @@ sub matchPredefineSwitch {
|
||||
}
|
||||
|
||||
my $stype = get_switchtype($vendor);
|
||||
if (exists($globalopt{pdu})) {
|
||||
$stype="pdu";
|
||||
}
|
||||
|
||||
send_msg($request, 0, "$device discovered and matched: $dswitch to $node" );
|
||||
|
||||
# only write to xcatdb if -w or --setup option specified
|
||||
if ( (exists($globalopt{w})) || (exists($globalopt{setup})) ) {
|
||||
if (exists($globalopt{pdu})) {
|
||||
xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$node,"otherinterfaces=$ip",'status=Matched',"mac=$mac","switchtype=$stype","usercomment=$vendor"] }, $sub_req, 0, 1);
|
||||
xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$node,"otherinterfaces=$ip",'status=Matched',"mac=$mac","usercomment=$vendor"] }, $sub_req, 0, 1);
|
||||
} else {
|
||||
xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$node,"otherinterfaces=$ip",'status=Matched',"mac=$mac","switchtype=$stype","usercomment=$vendor","switchtype=$stype"] }, $sub_req, 0, 1);
|
||||
xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$node,"otherinterfaces=$ip",'status=Matched',"mac=$mac","switchtype=$stype","usercomment=$vendor"] }, $sub_req, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1436,6 +1425,35 @@ sub switchsetup {
|
||||
my $request = shift;
|
||||
my $sub_req = shift;
|
||||
if (exists($globalopt{pdu})) {
|
||||
my $mytype = "pdu";
|
||||
my $nodetab = xCAT::Table->new('hosts');
|
||||
my $nodehash = $nodetab->getNodesAttribs(\@{${nodes_to_config}->{$mytype}},['ip','otherinterfaces']);
|
||||
# get netmask from network table
|
||||
my $nettab = xCAT::Table->new("networks");
|
||||
my @nets;
|
||||
if ($nettab) {
|
||||
@nets = $nettab->getAllAttribs('net','mask');
|
||||
}
|
||||
|
||||
foreach my $pdu(@{${nodes_to_config}->{$mytype}}) {
|
||||
my $cmd = "rspconfig $pdu sshcfg";
|
||||
xCAT::Utils->runcmd($cmd, 0);
|
||||
my $ip = $nodehash->{$pdu}->[0]->{ip};
|
||||
my $mask;
|
||||
foreach my $net (@nets) {
|
||||
if (xCAT::NetworkUtils::isInSameSubnet( $net->{'net'}, $ip, $net->{'mask'}, 0)) {
|
||||
$mask=$net->{'mask'};
|
||||
}
|
||||
}
|
||||
$cmd = "rspconfig $pdu hostname=$pdu ip=$ip netmask=$mask";
|
||||
xCAT::Utils->runcmd($cmd, 0);
|
||||
if ($::RUNCMD_RC == 0) {
|
||||
xCAT::Utils->runxcmd({ command => ['chdef'], arg => ['-t','node','-o',$pdu,"ip=$ip","otherinterfaces="] }, $sub_req, 0, 1);
|
||||
} else {
|
||||
send_msg($request, 0, "Failed to run rspconfig command to set ip/netmask\n");
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,24 +26,24 @@ sub findme {
|
||||
my $mtms = $request->{'mtm'}->[0] . "*" . $request->{'serial'}->[0];
|
||||
my $tmp_nodes = $::XCATVPDHASH{$mtms};
|
||||
my @nodes = ();
|
||||
my $bmc_node;
|
||||
my @bmc_nodes = ();
|
||||
my $bmc_node = undef;
|
||||
foreach (@$tmp_nodes) {
|
||||
if ($::XCATMPHASH{$_}) {
|
||||
$bmc_node = $_;
|
||||
push @bmc_nodes, $_;
|
||||
} else {
|
||||
push @nodes, $_;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($bmc_node) {
|
||||
if ($request->{'bmcmac'}->[0]) {
|
||||
my $bmcmac = lc($request->{'bmcmac'}->[0]);
|
||||
$bmcmac =~ s/\://g;
|
||||
my $tmp_node = "node-$bmcmac";
|
||||
$bmc_node = $tmp_node if ($::XCATMPHASH{$tmp_node});
|
||||
}
|
||||
if ($request->{'bmcmac'}->[0]) {
|
||||
my $bmcmac = lc($request->{'bmcmac'}->[0]);
|
||||
$bmcmac =~ s/\://g;
|
||||
my $tmp_node = "node-$bmcmac";
|
||||
push @bmc_nodes, $tmp_node if ($::XCATMPHASH{$tmp_node});
|
||||
}
|
||||
|
||||
$bmc_node = join(",", @bmc_nodes);
|
||||
my $nodenum = $#nodes;
|
||||
if ($nodenum < 0) {
|
||||
xCAT::MsgUtils->message("S", "xcat.discovery.mtms: ($request->{_xcat_clientmac}->[0]) Warning: Could not find any node for $mtms using mtms-based discovery");
|
||||
|
@ -1791,11 +1791,17 @@ sub updatenodesyncfiles
|
||||
if ($request->{SNFileSyncing}->[0] eq "yes") {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "File synchronization has completed for service nodes.";
|
||||
if (@::FAILEDNODES) {
|
||||
$rsp->{errorcode}->[0] = 1;
|
||||
}
|
||||
$callback->($rsp);
|
||||
}
|
||||
if ($request->{FileSyncing}->[0] eq "yes") {
|
||||
my $rsp = {};
|
||||
$rsp->{data}->[0] = "File synchronization has completed for nodes.";
|
||||
if (@::FAILEDNODES) {
|
||||
$rsp->{errorcode}->[0] = 1;
|
||||
}
|
||||
$callback->($rsp);
|
||||
}
|
||||
}
|
||||
|
@ -442,8 +442,7 @@ sub preprocess_request {
|
||||
if ($ntab) {
|
||||
foreach (@{ $ntab->getAllEntries() }) {
|
||||
next unless ($_->{dynamicrange});
|
||||
# if dynamicrange specified but dhcpserver was not - issue error message
|
||||
push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver})
|
||||
push @dhcpsvrs, $_->{dhcpserver} if ($_->{dhcpserver} && xCAT::NetworkUtils->nodeonmynet($_->{dhcpserver}));
|
||||
}
|
||||
}
|
||||
return xCAT::Scope->get_broadcast_disjoint_scope_with_parallel($req, $sn_hash, \@dhcpsvrs);
|
||||
@ -696,22 +695,19 @@ sub process_request {
|
||||
}
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: Finish to handle configurations");
|
||||
|
||||
# for offline operation, remove the dhcp entries
|
||||
if ($args[0] eq 'offline') {
|
||||
$sub_req->({ command => ['makedhcp'], arg => ['-d'], node => \@nodes }, $::XNBA_callback);
|
||||
}
|
||||
|
||||
#dhcp stuff -- inittime is set when xcatd on sn is started
|
||||
unless (($inittime) || ($args[0] eq 'offline')) {
|
||||
unless ($inittime) {
|
||||
my $do_dhcpsetup = 1;
|
||||
my @entries = xCAT::TableUtils->get_site_attribute("dhcpsetup");
|
||||
my $t_entry = $entries[0];
|
||||
if (defined($t_entry)) {
|
||||
if ($t_entry =~ /0|n|N/) { $do_dhcpsetup = 0; }
|
||||
}
|
||||
if ($do_dhcpsetup) {
|
||||
# For offline operation, remove the dhcp entries whatever dhcpset is disabled in site ( existing code logic, just keep it as is)
|
||||
if ($do_dhcpsetup || $args[0] eq 'offline') {
|
||||
my @parameter;
|
||||
push @parameter, '-l' if ($::request->{'_disparatetftp'}->[0]);
|
||||
push @parameter, '-l' if ($::XNBA_request->{'_disparatetftp'}->[0]);
|
||||
push @parameter, '-d' if ($args[0] eq 'offline');
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "xnba: issue makedhcp request");
|
||||
|
||||
$sub_req->({ command => ['makedhcp'],
|
||||
|
@ -7,6 +7,8 @@ BEGIN
|
||||
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
||||
}
|
||||
use lib "$::XCATROOT/lib/perl";
|
||||
use xCAT::NetworkUtils;
|
||||
|
||||
|
||||
sub handled_commands {
|
||||
return {
|
||||
@ -28,18 +30,11 @@ sub process_request {
|
||||
|
||||
#now, notify the node that its findme request has been processed
|
||||
my $client_ip = $req->{'_xcat_clientip'};
|
||||
xCAT::MsgUtils->message("S","Notify $client_ip that its findme request has been processed");
|
||||
my $sock = new IO::Socket::INET(
|
||||
PeerAddr => $client_ip,
|
||||
PeerPort => '3001',
|
||||
Timeout => '1',
|
||||
Proto => 'tcp'
|
||||
);
|
||||
if ($sock) {
|
||||
print $sock "processed";
|
||||
close($sock);
|
||||
}else{
|
||||
xCAT::MsgUtils->message("S", "Failed to notify $client_ip that its findme request has been processed");
|
||||
xCAT::MsgUtils->message("S","xcat.discovery.zzzdiscovery: Notify $client_ip that its findme request has been processed");
|
||||
#notify the client that its request is been processing
|
||||
my $ret=xCAT::NetworkUtils->send_tcp_msg($client_ip,3001,"processed");
|
||||
if($ret){
|
||||
xCAT::MsgUtils->message("S", "xcat.discovery.zzzdiscovery: Failed to notify $client_ip that its findme request has been processed");
|
||||
}
|
||||
}else{
|
||||
xCAT::MsgUtils->message("S", "xcat.discovery.zzzdiscovery: ($req->{_xcat_clientmac}->[0]) Successfully discovered the node using $req->{discoverymethod}->[0] discovery method.");
|
||||
|
@ -636,25 +636,9 @@ sub do_discovery_process {
|
||||
$vintage = time();
|
||||
} # site table reread every 15 second
|
||||
my $data;
|
||||
my $client;
|
||||
my $clientn;
|
||||
my $clientip;
|
||||
if (ref $msg eq 'HASH') { $data = $msg->{data}; } else { die "incorrect code to disco"; }
|
||||
my $saddr = $msg->{sockaddr};
|
||||
if ($inet6support) {
|
||||
($client, $sport) = Socket6::getnameinfo($saddr);
|
||||
($clientip, $sport) = Socket6::getnameinfo($saddr, Socket6::NI_NUMERICHOST());
|
||||
if ($clientip =~ /::ffff:.*\..*\./) {
|
||||
$clientip =~ s/^::ffff://;
|
||||
}
|
||||
if ($client =~ /::ffff:.*\..*\./) {
|
||||
$client =~ s/^::ffff://;
|
||||
}
|
||||
} else {
|
||||
($sport, $clientn) = sockaddr_in($saddr);
|
||||
$clientip = inet_ntoa($clientn);
|
||||
$client = gethostbyaddr($clientn, AF_INET);
|
||||
}
|
||||
my $clientip = $msg->{sockaddr};
|
||||
$sport=$msg->{sport};
|
||||
if ($data =~ /^\037\213/) { # per rfc 1952, these two bytes are gzip, and they are invalid for
|
||||
# xcatrequest xml, so go ahead and decompress it
|
||||
my $bigdata;
|
||||
@ -663,12 +647,10 @@ sub do_discovery_process {
|
||||
}
|
||||
my $req = eval { XMLin($data, SuppressEmpty => undef, ForceArray => 1) };
|
||||
if ($req and $req->{command} and ($req->{command}->[0] eq "findme" and $sport < 1000)) { # only consider priveleged port requests to start with
|
||||
$req->{'_xcat_clienthost'} = $client;
|
||||
$req->{'_xcat_clientip'} = $clientip;
|
||||
$req->{'_xcat_clientport'} = $sport;
|
||||
if (defined($cmd_handlers{"findme"}) and xCAT::NetworkUtils->nodeonmynet($clientip)) { # only discover from ips that appear to be on a managed network
|
||||
xCAT::MsgUtils->message("S", "xcatd: Processing discovery request from " . $req->{'_xcat_clientip'});
|
||||
|
||||
# Using cacheonly will cause the discovery processing running 2 times, cacheonly seems useless for switch.pm, so remove it
|
||||
#$req->{cacheonly}->[0] = 1;
|
||||
#plugin_command($req,undef,\&build_response);
|
||||
@ -678,7 +660,7 @@ sub do_discovery_process {
|
||||
|
||||
#}
|
||||
} else {
|
||||
xCAT::MsgUtils->message("S", "xcatd: Skipping discovery from " . $client . " because we either have no discovery plugins or the client address does not match an IP network that xCAT is managing");
|
||||
xCAT::MsgUtils->message("S", "xcatd: Skipping discovery from " . $clientip . " because we either have no discovery plugins or the client address does not match an IP network that xCAT is managing");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -801,10 +783,33 @@ sub do_udp_service { # This function opens up a UDP port
|
||||
foreach my $pkey (keys %packets) {
|
||||
my $saddr = $packets{$pkey}->[0];
|
||||
$data = $packets{$pkey}->[1];
|
||||
my $sport;
|
||||
my $clientip;
|
||||
my $clientn;
|
||||
if ($inet6support) {
|
||||
($clientip, $sport) = Socket6::getnameinfo($saddr, Socket6::NI_NUMERICHOST());
|
||||
if ($clientip =~ /::ffff:.*\..*\./) {
|
||||
$clientip =~ s/^::ffff://;
|
||||
}
|
||||
} else {
|
||||
($sport, $clientn) = sockaddr_in($saddr);
|
||||
$clientip = inet_ntoa($clientn);
|
||||
}
|
||||
if ($data =~ /^\037\213/) { # per rfc 1952, these two bytes are gzip, and they are invalid for
|
||||
store_fd({ data => $data, sockaddr => $saddr }, $discoctl); # for now, punt the gunzip to the worker process
|
||||
store_fd({ data => $data, sockaddr => $clientip, sport => $sport }, $discoctl); # for now, punt the gunzip to the worker process
|
||||
#notify the client that its request is been processing
|
||||
my $ret=xCAT::NetworkUtils->send_tcp_msg($clientip,3001,"processing");
|
||||
if($ret){
|
||||
xCAT::MsgUtils->message("S", "INFO xcatd: fail to notify $clientip that its 'findme' request is been processing");
|
||||
}
|
||||
} elsif ($data =~ /^<xcat/) { # xml format
|
||||
store_fd({ data => $data, sockaddr => $saddr }, $discoctl);
|
||||
store_fd({ data => $data, sockaddr => $clientip, sport => $sport }, $discoctl);
|
||||
#notify the client that its request is been processing
|
||||
my $ret=xCAT::NetworkUtils->send_tcp_msg($clientip,3001,"processing");
|
||||
if($ret){
|
||||
xCAT::MsgUtils->message("S", "INFO xcatd: fail to notify $clientip that its 'findme' request is been processing");
|
||||
}
|
||||
|
||||
} else { # for *now*, we'll do a tiny YAML subset
|
||||
if ($data =~ /^resourcerequest: xcatd$/) {
|
||||
$socket->send("ackresourcerequest\n", 0, $packets{$pkey}->[0]);
|
||||
@ -2436,35 +2441,12 @@ sub convey_response {
|
||||
# sanitize the response, to avoid being killed by non-printable bytes
|
||||
#$resp =~ tr/\011-\177/?/c;
|
||||
# seeing if using utf-8 offloads potential issues to client terminal, it didn't
|
||||
store_fd($resp, $parent_fd);
|
||||
yield; # parent must get timeslice anyway before an ack could possibly return
|
||||
my $parsel = new IO::Select;
|
||||
$parsel->add($parent_fd);
|
||||
my $selbits = $parsel->bits;
|
||||
my $rsp;
|
||||
while ($selbits && ($rsp = select($selbits, undef, undef, 5))) { # block up to five seconds
|
||||
|
||||
if ($quit) { # Obey quit flag
|
||||
xexit 0;
|
||||
}
|
||||
if ($rsp == 0) { # This means the filedescriptor was removed
|
||||
last;
|
||||
}
|
||||
if ($rsp < 0) { # A signal caused select to skip out, do-over
|
||||
next;
|
||||
}
|
||||
|
||||
# At this point, the only possibility is a positive return, meaning parent_fd requires attention of some sort
|
||||
$rsp = <$parent_fd>;
|
||||
if ($rsp) { # If data actually came in, last, otherwise, remove it from the IO::Select, but both should amount to the same thing
|
||||
last;
|
||||
} else {
|
||||
$parsel->remove($parent_fd);
|
||||
last;
|
||||
}
|
||||
eval {
|
||||
store_fd($resp, $parent_fd);
|
||||
};
|
||||
if ($@) {
|
||||
xCAT::MsgUtils->message("S", "Failed to store into socketpair: $@");
|
||||
}
|
||||
yield; # If still around, it means a peer process still hasn't gotten to us, so might as well yield
|
||||
$selbits = $parsel->bits;
|
||||
}
|
||||
|
||||
sub build_response {
|
||||
@ -2831,8 +2813,7 @@ sub service_connection {
|
||||
my $myxcatver=xCAT::Version->Version();
|
||||
if($req->{'_xcatver'}->[0] ne $myxcatver){
|
||||
my $myhostname=Sys::Hostname::hostname;
|
||||
my $resp = { warning => ["xCAT Version mismatch! \"$myxcatver\" on $myhostname does not match \"$req->{'_xcatver'}->[0]\" on $peerhost!"]};
|
||||
$resp->{serverdone} = [undef];
|
||||
my $resp = { warning => ["xCAT Version mismatch! \n $myhostname: $myxcatver\n $peerhost: $req->{'_xcatver'}->[0]\n"]};
|
||||
send_response($resp, $sock);
|
||||
}
|
||||
}
|
||||
@ -2987,9 +2968,10 @@ sub relay_fds { # Relays file descriptors from pipes to children to the SSL sock
|
||||
if ($@ and $@ =~ /^Magic number checking on storable file/) { # this most likely means we ran over the end of available input
|
||||
$fds->remove($rfh);
|
||||
close($rfh);
|
||||
} elsif ($@) {
|
||||
xCAT::MsgUtils->message("S", "Failed to retrieve from socketpair: $@");
|
||||
} else {
|
||||
push @$replyqueue, $resp;
|
||||
print $rfh "nfin\n";
|
||||
}
|
||||
}
|
||||
foreach my $rin ($clientselect->can_read(0)) {
|
||||
|
@ -91,7 +91,14 @@ if ($ENV{SSHCONSOLEPORT}) {
|
||||
$sshport= $ENV{SSHCONSOLEPORT};
|
||||
}
|
||||
|
||||
print "If the console cannot connect, please verify whether ssh keys has been configured on the bmc for $username user\n";
|
||||
# To automatically connect to the console without the need to send over the ssh keys,
|
||||
# ensure sshpass is installed on the Management and/or Service Nodes.
|
||||
print "If unable to open the console, ensure sshpass is installed or ssh keys have been configured on the BMC.\n";
|
||||
if (-x '/usr/bin/sshpass') {
|
||||
exec "/usr/bin/sshpass -p $password ssh -p $sshport -l $username -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $bmcip";
|
||||
} else {
|
||||
exec "ssh -p $sshport -l $username -o PasswordAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $bmcip";
|
||||
}
|
||||
|
||||
|
||||
exec "ssh -p $sshport -l $username $bmcip";
|
||||
|
||||
|
@ -34,3 +34,7 @@ perl-DBD-Pg
|
||||
wget
|
||||
util-linux-ng
|
||||
net-tools
|
||||
pciutils
|
||||
bind-utils
|
||||
strace
|
||||
tcpdump
|
||||
|
@ -59,7 +59,7 @@ do
|
||||
mv $i/postscripts /xcatpost
|
||||
rm -rf $i
|
||||
chmod +x /xcatpost/*
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/</</g' -e 's/>/>/g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /xcatpost/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>' |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/</</g' -e 's/>/>/g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /xcatpost/mypostscript
|
||||
MYCONT=`grep MASTER /xcatpost/mypostscript`
|
||||
MAX_RETRIES=10
|
||||
RETRY=0
|
||||
@ -72,12 +72,12 @@ do
|
||||
|
||||
let SLI=$RANDOM%10+10
|
||||
sleep $SLI
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/</</g' -e 's/>/>/g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /xcatpost/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/</</g' -e 's/>/>/g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /xcatpost/mypostscript
|
||||
MYCONT=`grep MASTER /xcatpost/mypostscript`
|
||||
done
|
||||
|
||||
|
||||
chmod +x /xcatpost/mypostscript
|
||||
chmod 700 /xcatpost/mypostscript
|
||||
GOTIT=1
|
||||
break
|
||||
fi
|
||||
|
@ -46,7 +46,7 @@ do
|
||||
chmod +x /xcatpost/*
|
||||
|
||||
# Get postscript to run on this node from xcat server
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
MYCONT=`grep MASTER /xcatpost/mypostscript`
|
||||
MAX_RETRIES=10
|
||||
RETRY=0
|
||||
@ -62,12 +62,12 @@ do
|
||||
sleep $SLI
|
||||
|
||||
# Get postscript to run on this node from xcat server
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
MYCONT=`grep MASTER /xcatpost/mypostscript`
|
||||
done
|
||||
|
||||
# Make executable
|
||||
chmod +x /xcatpost/mypostscript
|
||||
chmod 700 /xcatpost/mypostscript
|
||||
GOTIT=1
|
||||
break
|
||||
fi
|
||||
|
@ -46,7 +46,7 @@ do
|
||||
chmod +x /xcatpost/*
|
||||
|
||||
# Get postscript to run on this node from xcat server
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
MYCONT=`grep MASTER /xcatpost/mypostscript`
|
||||
MAX_RETRIES=10
|
||||
RETRY=0
|
||||
@ -62,12 +62,12 @@ do
|
||||
sleep $SLI
|
||||
|
||||
# Get postscript to run on this node from xcat server
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /xcatpost/mypostscript
|
||||
MYCONT=`grep MASTER /xcatpost/mypostscript`
|
||||
done
|
||||
|
||||
# Make executable
|
||||
chmod +x /xcatpost/mypostscript
|
||||
chmod 700 /xcatpost/mypostscript
|
||||
GOTIT=1
|
||||
break
|
||||
fi
|
||||
|
@ -52,7 +52,7 @@ do
|
||||
chmod +x /xcatpost/*
|
||||
|
||||
# Get postscript to run on this node from xcat server
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /tmp/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /tmp/mypostscript
|
||||
MYCONT=`grep MASTER /tmp/mypostscript`
|
||||
MAX_RETRIES=10
|
||||
RETRY=0
|
||||
@ -67,12 +67,12 @@ do
|
||||
sleep $SLI
|
||||
|
||||
# Get postscript to run on this node from xcat server
|
||||
/xcatpost/getpostscript.awk |sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /tmp/mypostscript
|
||||
/xcatpost/getpostscript.awk |egrep '<data>'|sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /tmp/mypostscript
|
||||
MYCONT=`grep MASTER /tmp/mypostscript`
|
||||
done
|
||||
|
||||
# Make executable
|
||||
chmod +x /tmp/mypostscript
|
||||
chmod 700 /tmp/mypostscript
|
||||
GOTIT=1
|
||||
break
|
||||
fi
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user