2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-09-29 00:31:09 +00:00

Compare commits

..

1573 Commits

Author SHA1 Message Date
Jarrod Johnson 7622145fea Fall back to x64 if the aarch64 location didn't pan out 2026-07-13 10:01:04 -04:00
Jarrod Johnson 678bd53857 Correct paths to aarch64 boot material in imgutil 2026-07-13 09:23:33 -04:00
Jarrod Johnson 3295778566 Improve webauthn error handling and tighten up routing
If not webauthn, have authorize
bail out on webauthn request instead
of a sessionless authdata.

For some "special" HTTP paths, tighten up routing rules.
2026-07-08 12:03:48 -04:00
Jarrod Johnson b3acf011bd Restart vtbufferd on exit
Notably, if you strace it, it will trigger an exit(1).  There was at least one documented segmentation fault as well.

Buffer content is lost in such an event, but service remains running.
2026-07-02 12:20:01 -04:00
Jarrod Johnson dc4cafc29f Rework autoconsole logic
Match autocons

Skip unless EFI x86_64.

If SPCR, trust it and use that unconditionally.

Otherwise, if only one can respond to TIOCMGET, then use that one.

If multiple can respond, but exactly one shows carrier, use that.
2026-06-25 16:41:32 -04:00
Jarrod Johnson 3340585fb4 Only count copernicus replies that have OK status 2026-06-25 15:24:31 -04:00
Jarrod Johnson 4456767122 When possible, check confluent user access to file
If a confluent user is a system user, do not allow them to
upload paths that their user would not have access to otherwise.

For non-system users, continue with the path based banned behavior.
2026-06-25 12:15:13 -04:00
Jarrod Johnson 556bb1d0ff Prevent staging of files from indicating path traversal 2026-06-25 10:09:59 -04:00
Jarrod Johnson a201e9886e Have messages force normalizing the incoming filenames
This avoids downstream code that may expect specific locations from being confused.
2026-06-25 09:48:40 -04:00
Jarrod Johnson f82993efe7 Fix debian deployment on slow network link up
When network link was slow to establish, it would fall right through
the network initilalization code.

Now keep working it until a result is acheived.
2026-06-25 08:37:19 -04:00
Jarrod Johnson f8366a50ef Do not set 0.0.0.0 gateway 2026-06-24 15:59:10 -04:00
Jarrod Johnson d369dcac55 Fix non-bonding configuration of ubuntu 2026-06-16 12:42:03 -04:00
Jarrod Johnson 3b2d92a219 Correct typo in pthread name 2026-06-08 11:00:40 -04:00
Jarrod Johnson ffacb66c62 Update rdma vintage 2026-06-08 10:56:26 -04:00
Jarrod Johnson 2073f421da Add libraries to genesis 2026-06-08 10:54:50 -04:00
Jarrod Johnson ed2eed66dc Allow nodedeploy to request http boot specifically 2026-06-03 09:28:44 -04:00
Jarrod Johnson d8f9b6c8e6 Add support for http boot
Some redfish require us to be very specific.
2026-06-03 09:12:46 -04:00
Jarrod Johnson d9a18a7bf6 Actually use the interposer for firmware update 2026-06-01 19:52:43 -04:00
Markus Hilger 439a930188 confignet: Fix interface type detection for IB VFs
IB VFs have the following "ip l" output:

4: ibp129s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 2044 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/infiniband 00:00:00:8d:fe:80:00:00:00:00:00:00:60:5e:65:03:00:2c:43:c8 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    vf 0     link/infiniband 00:00:00:8d:fe:80:00:00:00:00:00:00:60:5e:65:03:00:2c:43:c8 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff, spoof checking off, NODE_GUID 00:00:00:00:00:00:00:00, PORT_GUID 00:00:00:00:00:00:00:00, link-state enable, trust off, query_rss off
5: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
    link/ether 30:56:0f:17:c0:b4 brd ff:ff:ff:ff:ff:ff
    altname enp196s0
    altname enx30560f17c0b4

This breaks the detection script because index 0 of the "vf 0 ..." line is not link/<type> anymore.
This commit improves the detection logic to fix this.
2026-06-01 19:30:54 -04:00
Jarrod Johnson 00b2afd42b Fixes for confignet for Ubuntu
Try to find various layers of network config and normalize.

Ultimately, after post subiquity will do some things and easiest to fix in firstboot instead.
2026-06-01 16:49:42 -04:00
Jarrod Johnson 90c2a4cf73 Fix iterating the netplan configuration 2026-06-01 12:55:11 -04:00
Jarrod Johnson c691dc7159 Remove cloud-init netplan if redundant 2026-06-01 09:33:25 -04:00
Jarrod Johnson a7c188b812 Add support for passing a parameterfile in updates 2026-06-01 07:51:22 -04:00
Jarrod Johnson 5ba43ecaa0 Add bonding to netplan management 2026-05-26 10:06:49 -04:00
Vinícius Ferrão 2f53d3bde6 Include xen-front drivers in confluent-curated initramfs 2026-05-23 14:21:13 -04:00
Jarrod Johnson 9fe9e8672a Support more states 2026-05-21 10:03:08 -04:00
Jarrod Johnson 0fe60175f3 Add missing close 2026-05-21 08:36:16 -04:00
Jarrod Johnson d411041243 Recognize more storage states 2026-05-20 16:14:24 -04:00
Jarrod Johnson cc101d12bc Port diskless enhancements from el9 to ubuntu 2026-05-20 15:30:23 -04:00
Jarrod Johnson 2f08ee81f2 Fix off by one in urlmount 2026-05-20 12:37:36 -04:00
Jarrod Johnson 1e9231eea6 Add megasol method 2026-05-19 09:17:50 -04:00
Jarrod Johnson 24cb05e535 Fix name of ssh in various ubuntu scripts 2026-05-13 13:52:05 -04:00
Jarrod Johnson 72b95abb4f Add missing syncfiles examples to ubuntu profiles 2026-05-13 13:51:59 -04:00
Jarrod Johnson 57a170d0d8 Implement a headless mode
For automation, this can make more sense.
2026-05-12 11:23:37 -04:00
Jarrod Johnson daeabc6fe5 Add expression support to the nodeconsole automation 2026-05-11 16:51:01 -04:00
Jarrod Johnson 28a8f6f0d6 Provide automation facility for nodeconsole
Allow nodeconsole to walk console according to a script
2026-05-11 13:55:54 -04:00
Jarrod Johnson 7542897b43 Normalize perms to int or None 2026-05-07 09:44:00 -04:00
Jarrod Johnson c69952265f Permit override of unix ownership/permissions on sockets
If an environment knows more specifically what should have access in terms of group, allow service.cfg to indicate.
2026-05-07 08:44:16 -04:00
Jarrod Johnson 01cc86fa55 Add a '-r' argument to refresh site contents
If an environment manually manages all materials,
provide -r to let
them request packing of those materials
without trying to generate any of the content.
2026-05-06 08:46:31 -04:00
Jarrod Johnson d6e3c7e837 Backport cert fix 2026-05-05 16:26:49 -04:00
Jarrod Johnson dcb6aeca65 Add ca-only policy
This policy forces CA validation every time.

This also checks things like date validity.
2026-05-05 14:41:02 -04:00
Jarrod Johnson 7bc76b62e6 Backport CA policy changes 2026-05-05 11:31:26 -04:00
Jarrod Johnson db313628c5 Include aarch64 names for key libraries in ubuntu diskless 2026-05-01 14:25:18 -04:00
Jarrod Johnson f260323d2f Fix missing ubuntu diskless content 2026-05-01 12:14:13 -04:00
Jarrod Johnson d60bc7f524 Bring chrony fixes to other scripts 2026-04-30 11:24:20 -04:00
Jarrod Johnson ff0d4cdadf Fix diskless profiles for chrony.conf modification 2026-04-30 11:24:15 -04:00
Timothy Middelkoop db6475c4da Fix el8/el9 hook paths corrupted by symlinked el10 in aarch64 spec
In confluent_osdeploy-aarch64.spec.tmpl, el10 was created as a symlink
to el8, so the subsequent `mv el10/initramfs/usr el10/initramfs/var`
inadvertently renamed el8's usr directory, leaving el8 and el9 (also
symlinked to el8) with hooks at var/lib/dracut/hooks/ instead of
usr/lib/dracut/hooks/. Rocky 9 dracut never found the hooks and dropped
to the emergency shell on all aarch64 nodes.

Use `cp -a el8 el10` as the x86_64 spec already does, so the rename
only affects the el10 copy.

Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Timothy Middelkoop <tmiddelkoop@internet2.edu>
2026-04-30 08:09:06 -04:00
Jarrod Johnson 6d27e8a009 Allow monitor to read attributes by 'all' resource. 2026-04-29 07:51:08 -04:00
Jarrod Johnson f363796439 Write to stdout as binary
This allows better redirection.

In python3, must write to sys.stdout.buffer.  AttributeError for the unlikely event of a python2 based node being deployed.
2026-04-29 07:45:49 -04:00
Jarrod Johnson dec118a985 Fix mistake in spec file 2026-04-24 09:29:31 -04:00
Jarrod Johnson 38eb0d7b10 Add Ubuntu 26.04 2026-04-24 08:35:44 -04:00
xu_ren_xian ae338daa43 Handle confluent= boot arg and IPv4 NIC autodetect
Add support for a confluent=<host> kernel argument in init-premount: configure networking, flush interfaces, autodetect the primary NIC (saved to /tmp/autodetectnic), verify TLS connectivity to the provided server, call the whoami endpoint over TLS to obtain the node name, and write results to /custom-installation/confluent/confluent.info (with fallback to copernicus on failure).

Also update casper-bottom logic to handle IPv4 manager addresses: for IPv6 the manager is still bracketed and scoped interface resolved as before; for IPv4 the script now uses the previously detected NIC (/tmp/autodetectnic) or falls back to an `ip route get <mgr>` lookup to determine DEVICE. This ensures routed IPv4 deployments work correctly.
2026-04-23 17:50:41 -04:00
Jarrod Johnson 6ad3f0d70c Fix mistakes in the node apoption samples 2026-04-20 09:46:45 -04:00
Jarrod Johnson c0b9bb3ab1 Fix group rename in collective 2026-04-17 11:57:35 -04:00
Jarrod Johnson b32755b0d3 Fix remote client operation with Python 3.12+ 2026-04-17 09:01:12 -04:00
Jarrod Johnson c54ac530e1 Handle some environments where timedatectl does not exist 2026-04-14 13:50:12 -04:00
Jarrod Johnson 8990622470 Improve certificate mismatch handling 2026-04-08 15:37:50 -04:00
Jarrod Johnson 93a35d7e77 Improve srlinux error handling 2026-04-08 15:30:43 -04:00
Jarrod Johnson c49b2fd8ab Update quorum on deletion
If deletion of a node brings quorum, notify followers
of the good news
2026-04-07 14:57:09 -04:00
Jarrod Johnson 3ce2a5bc26 More tightly constrain node profile requests
Normalize paths using abspath and validate the result is within the expected path.
2026-04-06 15:12:44 -04:00
Jarrod Johnson 69d984b9dc Fix syntax mistake in deferred handling in nodeapply 2026-04-03 10:34:20 -04:00
Jarrod Johnson a123165712 Improve error when unknown user specified in syncfiles 2026-04-02 15:29:31 -04:00
Jarrod Johnson b91b10552c EL10 doesn't do setgid keysign
chmod 600 instead
2026-03-25 12:59:40 -04:00
Jarrod Johnson 779b07d2c2 Only try to use ssh_keys if it exists
EL10 changed from using ssh_keys and setgid to just
do setuid root instead.
2026-03-25 12:56:16 -04:00
Jarrod Johnson df73c14475 Support unconfigured good without space
Some platforms try to combine the words
2026-03-19 18:05:38 -04:00
Jarrod Johnson f78b301143 Update usage text 2026-03-19 09:54:08 -04:00
Jarrod Johnson 9b00fe5521 Don't try to open a file that doesn't exist 2026-03-17 13:03:18 -04:00
Jarrod Johnson 13a6444541 Fix incorrectly matching older versions as 'el10' 2026-03-17 12:58:04 -04:00
Jarrod Johnson 52db46be93 Fix python detection from ansible with space in shebang 2026-03-13 11:41:16 -04:00
Jarrod Johnson 550dfbf6a0 Fix reference of inputdata in remoteconfig 2026-03-13 09:26:11 -04:00
Jarrod Johnson e0951b11a6 Fix filename typo 2026-03-13 08:58:58 -04:00
Jarrod Johnson 1a87701fee Fix ansible running
Have results available as they happen

change away from stdout, to avoid being stepped on by ansible modules that print to that
2026-03-09 16:48:42 -04:00
Jarrod Johnson e185f2224f Implement ability for user to kick off confluent ansible runs
Add nodeapply -A and associated API.

This permits orchestrating plays without touching the nodes directly by the user.
2026-03-06 16:24:26 -05:00
Jarrod Johnson 69beaad3c9 Induce more versions of openssh to do the proper thing 2026-02-23 15:07:19 -05:00
Jarrod Johnson 74dda48513 Provide helper script for setting up nokia switches 2026-02-23 10:15:55 -05:00
Jarrod Johnson 08b2e1d008 Wire up FDB and LLDP for srlinux 2026-02-18 16:53:12 -05:00
Jarrod Johnson 582842aec8 Add mac and lldp retrieval for SRLinux 2026-02-18 16:16:22 -05:00
Jarrod Johnson 63307c331e Have nodesensors and nodehealth be more adaptive to partial server data. 2026-02-17 16:19:41 -05:00
Jarrod Johnson 318608cde3 Add draft SRLinux support
Wire up the non-networking facets of Nokia SR Linux support.

Provide stubs for LLDP and FDB
2026-02-17 16:13:43 -05:00
Jarrod Johnson ef7d2414ad Update nodeconfig usage material 2026-02-11 11:35:09 -05:00
Jarrod Johnson 722a0b874a Add notation about certificate and nodemedia 2026-02-11 10:54:30 -05:00
Jarrod Johnson 1deb76989e Recognize 1a/2b style enclosure bay in discovery 2026-02-10 17:10:18 -05:00
Jarrod Johnson 480d399f44 Add missing switch member of info with NX switches 2026-02-09 13:17:45 -05:00
Jarrod Johnson 07369667f7 Become incompatible with pysnmp 7.1.16
The EPEL version of pysnmp is broken, block it from dependecies
2026-02-06 15:13:46 -05:00
Jarrod Johnson e1d4b72f32 Be less picky about megarac url
megarac implementations consistently indicate an .xml file, but wildly vary on what it may be.

Broaden recognition.
2026-02-05 07:57:25 -05:00
Jarrod Johnson 86783a2f12 Fix uninitialized privacy_protocol variable 2026-02-03 07:58:07 -05:00
Jarrod Johnson 99063eb049 Recognize variation in DeviceDescrption.json to see SMM3 2026-02-02 10:17:32 -05:00
Jarrod Johnson 0975bd9e62 Revert "Update some code for async"
This reverts commit 3058dd4141.
2026-01-28 15:04:49 -05:00
Jarrod Johnson 3058dd4141 Update some code for async 2026-01-28 14:49:58 -05:00
Jarrod Johnson 21c9158491 Carry forward some dns attributes into a bond 2026-01-21 15:12:23 -05:00
Jarrod Johnson e6c19388a2 Add device-manager to container build
Confluent needs device-mapper for imgutil operation
2026-01-16 08:45:12 -05:00
Jarrod Johnson 048780e16d Explicitly mknodes for pack/unpack
In some contexts, udev may be asleep
at the wheel. Explictly have dmsetup
refresh the devnodes.
2026-01-15 15:15:11 -05:00
Jarrod Johnson 61d7a49163 Revert "Fallback to filename for PE format kernels"
This reverts commit a0a5887214.
2026-01-15 14:29:31 -05:00
Jarrod Johnson f8b8ce3847 Fallback to filename for PE format kernels
Some ARM64 kernels ship as EFI executables, but it's
not obvious how to extract version numbers from those properly.
2026-01-15 14:29:23 -05:00
Jarrod Johnson a0a5887214 Fallback to filename for PE format kernels
Some ARM64 kernels ship as EFI executables, but it's
not obvious how to extract version numbers from those properly.
2026-01-15 13:27:21 -05:00
Jarrod Johnson ccaf22f44f Add architecture handling in pkglist
To handle amd64/arm64 profiles, have the pkglist allow for architecture specific qualifiers.

Additionally, soften failure to accomplish selinux changes.
2026-01-15 12:52:07 -05:00
Jarrod Johnson 72c4868073 Update container with more packages, volumes, env, and alma 10 2026-01-15 09:46:23 -05:00
Jarrod Johnson afb6356f9d Change ownership
Container runs as internal 'root' user for now
2026-01-14 16:29:31 -05:00
Jarrod Johnson 6e6ac67b3d Provide some build assets
Provide some dockerfiles for creating build containers
2026-01-13 13:57:37 -05:00
Jarrod Johnson 99d10896e8 Fix parameter count unpack for accelerated switch interrogation 2026-01-08 17:07:39 -05:00
Jarrod Johnson 488f23e3ed Fix spelling of rpmbuild 2026-01-06 15:55:36 -05:00
Jarrod Johnson 6ca62cbb35 Provide optional output directory 2026-01-06 15:54:46 -05:00
Jarrod Johnson 45bc9788b4 Correct mistake in SPECS spelling 2026-01-06 15:51:40 -05:00
Jarrod Johnson 289c31e7ac Ensure in expected directory to start 2026-01-06 15:51:06 -05:00
Jarrod Johnson 1a684f2012 Ensure rpmbuild directory exists before building 2026-01-06 15:49:50 -05:00
Jarrod Johnson a4229fc58d Change name to index in apiclient
confignet was using the index for ipv4
2025-12-12 11:18:33 -05:00
Jarrod Johnson 31c1a865dc Update confignet to match apiclient changes 2025-12-12 09:30:56 -05:00
Jarrod Johnson ff84fcf6e9 Merge branch '3.14' 2025-12-11 13:21:33 -05:00
Jarrod Johnson 56dfb6dc6b Fix spelling issue in man page 2025-12-11 08:46:59 -05:00
Jarrod Johnson d7577a04a7 Fix ESXi compatibility of apiclient
apiclient was using Linux specific network  information.

Change to libc getifaddrs for better cross-platform compatibility.
2025-12-11 08:46:19 -05:00
Jarrod Johnson b72d6c9cfc Fix typo 2025-12-10 14:14:14 -05:00
Jarrod Johnson 523c93dfc3 Tolerate more network circumstances in bluefield deploy
If the networking didn't come up well, the 'functions' routines would not be able to handle.

Switch to using apiclient which is designed specifically to handle less cooperative
initial network conditions.
2025-12-09 08:49:27 -05:00
Jarrod Johnson c8745292bf Handle broader memory information being returned from confluent 2025-12-04 13:28:45 -05:00
Jarrod Johnson 75e7b9040b Add more imgutil documentation 2025-12-04 13:27:48 -05:00
Jarrod Johnson 04e983a2d3 Handle broader memory information being returned from confluent 2025-12-04 09:52:15 -05:00
Jarrod Johnson 2464e0ff4f Fix location of the apiclient common resource 2025-12-02 14:35:50 -05:00
Jarrod Johnson c196bf9d55 Fix initial startup of a new confluent
The indexes change failed on a brand new install.
2025-12-02 14:31:10 -05:00
Jarrod Johnson 12d886a4f6 Add more imgutil documentation 2025-11-25 13:19:03 -05:00
Jarrod Johnson 6a26ece782 Merge remote-tracking branch 'xcat/master' 2025-11-25 11:59:43 -05:00
Jarrod Johnson 3cbac38d57 Also autoconsole when exactly one serial port is detected at all. 2025-11-25 11:53:50 -05:00
Jarrod Johnson 224f349053 Extend autocons to more use cases
If SPCR comes up blank, see if there is one and exactly one serial with carrier detect

Failing that, give DMI a chance to indicate a preference, for now just SuperMicro, since they have the most
inconsistent carrier detect behavior
but almost always consider ttyS1 to be the answer.
2025-11-25 11:51:07 -05:00
Jarrod Johnson 9d361d376d Merge pull request #203 from Obihoernchen/bond_desc
Add bond alias to team description
2025-11-21 09:47:09 -05:00
Markus Hilger ec39de3df0 Add bond alias to team description 2025-11-21 14:16:07 +01:00
Jarrod Johnson a3b768c70f Draft bluefield deploymeent facilities 2025-11-20 16:44:24 -05:00
Jarrod Johnson 4f75d4942b Modify adoption process:
Restore useinsecureprotocols if set directly on node

Switch from pxe-style to identity-file based node api token for hardened node authentication
2025-11-20 16:05:22 -05:00
Jarrod Johnson 4d2f36917c Restore useinsecureprotocols after adopt 2025-11-20 15:49:51 -05:00
Jarrod Johnson a2a50d34d1 Merge remote-tracking branch 'xcat' 2025-11-19 15:38:01 -05:00
Jarrod Johnson 041008a524 Remove redundant el10 initramfs fixup 2025-11-19 15:37:29 -05:00
Jarrod Johnson 5923feaa18 Merge pull request #202 from Obihoernchen/custom
Add documentation for custom nodeattribs
2025-11-19 07:47:46 -05:00
Jarrod Johnson 73216fc062 Fix architecture name mismatch
Confluent went with aarch64 consistent
with EL naming, but Ubuntu used
debian naming, recognize and just
handle that.
2025-11-18 09:10:30 -05:00
Jarrod Johnson 100944490c Fix potentially uninitialized curridx 2025-11-17 15:07:17 -05:00
Jarrod Johnson 61b07e0af4 Start index at 1 instead of 0 2025-11-17 12:05:03 -05:00
Jarrod Johnson 53760ab5dd Attribute feature enhancement
Add expression functions upper, lower, block_number, and block_offset.

Add an 'id.index' auto-attribute to
yield a number for nodes.
2025-11-17 11:58:04 -05:00
Jarrod Johnson d3e7a49f92 Simplify by recursion
Use _handle_ast_node to process
everything before the function name in an Attribute call
2025-11-15 10:32:11 -05:00
Jarrod Johnson 1f688ead28 Implement .replace() for attribute expressions
Provide an easy to use replace() to allow removing or substiting values
during expression evaluation.
2025-11-14 17:20:06 -05:00
Jarrod Johnson d20c5ac6eb Move handling of the loop directio straight to onboot
There were difficulties in the devfs after
boot, just let the full system handle it.
2025-11-13 15:33:04 -05:00
Jarrod Johnson 4484216198 Fix issues with the tethered memory optimizations 2025-11-13 15:24:26 -05:00
Jarrod Johnson e1efd6a9c5 Implement new 'uncompressed' image method
This allows the FS to just live, uncompressed, in cache.

This is generally a bad idea, however:

- In a hypothetically super-tuned diskless image, the lack of double-cache can offset the lack of compression
- The image will have supreme read performance
- It will have the most deterministic memory behavior
2025-11-13 14:39:53 -05:00
Jarrod Johnson 58d5209595 Port tethered improvments to EL8 2025-11-13 14:35:18 -05:00
Jarrod Johnson 53c918042a Remove double-caching in tethered diskless
By default, the squashfs file was being cached as well as the contents after extraction.

This is superfluous pressure on the cache of the OS.

However, it does help keep the image afloat through 'confignet', so
leave it on until onboot completes, then reclaim cache and disable further caching.
2025-11-13 14:28:25 -05:00
Markus Hilger 9148a841b5 Add documentation for custom nodeattribs 2025-11-13 00:45:53 +01:00
Jarrod Johnson 6ebb6de107 Allow specifiying SNMP privacy protocol
Modern SNMP devices may require AES.

Unfortunately, older ones may refuse AES.

For compatibility, continue to default to DES, but
allow AES to be indicated in attributes.
2025-11-10 10:21:01 -05:00
Jarrod Johnson d2d77ab1d5 Do not let diskless.conf persist into EL9 diskless images
It fouls run of kdump building the kdump image.
2025-11-07 13:23:44 -05:00
Jarrod Johnson 20292cdfd0 Do not let diskless.conf persist into EL9 diskless images
It fouls run of kdump building the kdump image.
2025-11-07 13:22:21 -05:00
Jarrod Johnson b07da455c2 Fix SAN generation
The nameconstraint support missed
a branch, fix this.
2025-11-07 11:22:12 -05:00
Jarrod Johnson cc9a81103b Do not autosign if the corresponding cryptography is unavailable
We use cryptography verification, but it's relatively new.

For compatibility, we fall back to fingerprint only.

This is pretty bad when inflicted on
unsuspecting users on autosign,
so skip autosign if cert validation
would break.
2025-11-04 15:51:22 -05:00
Jarrod Johnson 21155d2091 Bring untethered changes to el10 diskless 2025-11-04 11:17:28 -05:00
Jarrod Johnson 6c0d7ea60e Simplify end untethered el9 diskless environment
Rather than treat both as the same, since untethered has everything up front anyway, go ahead and extract the filesystem.

This makes the mount look more straightforward and makes it so deletion of files from
the image also frees ram.
2025-11-04 11:14:52 -05:00
Jarrod Johnson 174d204607 Implement compatibility with newer pysnmp
For now, terminate the async nature
if newer pysnmp is detected.
2025-11-04 09:58:11 -05:00
Jarrod Johnson 2826abb7ab Prune excessive leftover ext config files 2025-11-03 14:21:36 -05:00
Jarrod Johnson 5adb5fa780 Automatically sign XCC certificates on discover
If an XCC doesn't have a 'real' certificate, sign it with the confluent
CA for 47 days.
2025-11-03 14:02:33 -05:00
Jarrod Johnson 5de063212f Prepare for supporting constrained CA
If asked to sign using a name constrained CA,
avoid generating a certificate that
would violate those constraints.
2025-11-03 10:43:34 -05:00
Jarrod Johnson 073f6d1389 Wire up cert signing to nodecertutil 2025-10-31 12:04:27 -04:00
Jarrod Johnson f755ba9f91 Implement method to sign BMC certificates 2025-10-31 10:46:42 -04:00
Jarrod Johnson cf8c01ef13 Merge remote-tracking branch 'lenovo' 2025-10-31 09:48:05 -04:00
Jarrod Johnson ce8531375a Update to handle newer XCC2 firmware 2025-10-31 09:46:23 -04:00
Jarrod Johnson 8b12047ae0 Update to handle newer XCC2 firmware 2025-10-31 09:45:59 -04:00
Jarrod Johnson f0a779764d Fix ordering of digest argument
The digest argument was erroneously inserted between startdate and it's
argument, correct this mistake.
2025-10-28 15:39:04 -04:00
Jarrod Johnson 0ad7e99efe Only optionally use cryptography verification
Some supported distributions can't run the newer cryptography.

Make it a feature that only works with newer platforms.
2025-10-27 08:38:14 -04:00
Jarrod Johnson 24a76612ae Use sha284 hash algorithm
Some implementations reject sha256 as inadequate if ecdsa has 384 bit keylength. Bring the digest up to match
the key size for the ECDSA.
2025-10-27 06:41:05 -04:00
Jarrod Johnson 6c9c58f464 Update certutil to prepare for broader usage
For one, apply more rules from CA/B forum. This includes including KU and EKU extensions, marking basicConstraints critical, and
randomized serial numbers.

Also make the backdate and end date configurable, to allow
for the BMC certs to have a more palatable validity interval.
2025-10-26 14:57:26 -04:00
Jarrod Johnson 3125f4171b Begin overhaul of TLS cert management
Begin expanding certutil to sign other certificates from external CSRs more easily.

Have certutil make the CA constraint critical.

Have the fingerprint based validator have a mechanism to check for properly signed certificate in lieu of exact match,
and update the stored fingerprint
on match.

Provide a means to request a custom subject when evaluating a
target.

Change redfish plugin to set that subject in the verifier.
2025-10-24 20:02:51 -04:00
Jarrod Johnson 762adb882a Track client address on checkin
When doing DHCP deployment in particular, it's good to track what the actual ip was.
2025-10-21 13:04:30 -04:00
Jarrod Johnson 36687069aa Fix ESXi8 deployment
The changes for getinstalldisk assumed functionality
in ESXi9.  Target older
functional level for our purposes.

Also expand the fallback to cover cases where the disk interrogation fails.
2025-10-21 11:11:52 -04:00
Jarrod Johnson 11ff2dabfc Clean up kickstart networking
Try to apply hostname through localcli, since
hostname is unsupported through net if dhcp.

Also more affirimatively indicate dhcp.
2025-10-17 10:00:38 -04:00
Jarrod Johnson f9351484a4 Add fallback if getinstalldisk detects no preferred disks 2025-10-17 09:32:33 -04:00
Jarrod Johnson b22c17208a Stop preferring HWE for now
The HWE has some missing hardware support, ironically...
2025-10-16 18:30:46 -04:00
Jarrod Johnson 4982ac1a17 Bump genesis version 2025-10-15 16:51:21 -04:00
Jarrod Johnson a43d7e11e2 Implement an esxi getinstalldisk 2025-10-15 10:43:36 -04:00
Jarrod Johnson c5896c056e Add facility to manage BMC CA certs
For redfish at least, we can manage
some BMC CA certificate trust stores.
2025-10-14 14:30:27 -04:00
Jarrod Johnson a73dced80b Fix configbmc on XCC3
IPv4 based configbmc is now fixed for multi-nic XCC3 configurations.
2025-10-14 13:19:28 -04:00
Jarrod Johnson b6188683b8 Redirect 'xcc' to 'xcc3' for bmcconfig -c 2025-10-14 10:22:15 -04:00
Jarrod Johnson 50243b67d5 Add a more helpful error when bmc not set
When doing a configbmc, need to present
a more reasonable message about lack of address.
2025-10-08 14:20:44 -04:00
Jarrod Johnson 7cdfcd4913 Implement support for multi-manager XCC managed systems 2025-10-08 09:42:17 -04:00
Jarrod Johnson 179ad4e196 Fix IPv6 redfish config fetch for select targets
Not all targets offer up static gateway
2025-10-08 09:39:17 -04:00
Jarrod Johnson be2ae57a38 Skip the '[' when evaluating partial ESC for terminator 2025-10-06 17:34:17 -04:00
Jarrod Johnson f34395648e Add vlan_id management to redfish and ipmi plugins 2025-10-06 17:28:55 -04:00
Jarrod Johnson 3f5d96788e Fix handling of split SGR payloads
Surprisingly frequently, the firmware stacks split right after the \x1b byte in
sending data down. Defer a dangling partial sequence until more data
comes in that should make it complete.
2025-10-06 13:12:43 -04:00
Jarrod Johnson 17866d7657 Change to only force intense if bg == fg
In the interest of interfering with terminal behavior as little as possible,
only apply the forced intensity if the background and foreground color are
identical and would make it otherwise literally impossible to read
when working as designed.
2025-10-06 12:22:21 -04:00
Jarrod Johnson a1144fd49a Auto-intense color
Terminals seem to expect 'bold or intensity' to imply intense color.

There are certain terminals that steadfastly refuse to do bold and intense. So implement the logic on behalf of
the remote terminal.

Commonly, UEFI setup menus request bold white text on white background. This fixes such menus to be readable by explicitly requesting intense white foreground rather than normal background. For example, the kitty terminal has no 'intense on bold feature.
2025-10-06 10:48:35 -04:00
Jarrod Johnson c472d96406 Add '-r' to nodedeploy
This allows a shorthand to request a redeploy of whatever the most appropriate profile is.
2025-10-06 08:24:17 -04:00
Jarrod Johnson 02791418bc Support attribute expansion in filenames
For nodemedia, nodelicense, and nodefirmware, support
for expressions in filenames was
fouled when pass by
filehandle was added.

Restore this by adding all the files matching an expression.
2025-10-02 15:45:48 -04:00
Jarrod Johnson 2d29813320 Store device for future use in ubuntu deployment 2025-10-02 14:28:46 -04:00
Jarrod Johnson a9d15de156 Rework Ubuntu identity image DHCP bringup
The stock Ubuntu approach was inadequate.  It would DHCP out every nic and take the fastest result, and no going back.

Now the CDC nic can frequently win that race.

First, rmmod cdc_ether, as a scenario that is completely right out.

But beyond that, let Ubuntu have one shot at multi-nic bringup.  Beyond that, maintain a list of all link-up devices.

If the check should fail, then start doing one nic at a time, cycling through them.

Also, the openssl s_client timeout is painfully slow, use subshell and kill to speed up things.
2025-10-02 10:55:43 -04:00
Jarrod Johnson a4ba92a2e7 Retry network bringup
ESXi may be slow in being ready for network bringup. Workaround
by retrying.
2025-10-01 13:08:17 -04:00
Jarrod Johnson 6938bba2d3 Have confignet pause until connectivity restored
If we are reconfiguring network for a diskless node, wait for
things to settle back in before continuing.
2025-09-26 13:42:29 -04:00
Jarrod Johnson 871685ea20 Correct missing closure of if 2025-09-25 15:49:25 -04:00
Jarrod Johnson a480cc73df Add connectivity check to esxi ident bringup
If using the identity image bringup
with dhcp, be more careful about waiting
for connectivity before proceeding.
2025-09-25 15:29:33 -04:00
Jarrod Johnson 39eb32df38 Test connection on net cfg apply
When network configuration is applied, wait until we
can reach the deployment server again before exiting.

This should make us more robust against various potential delays after
changing the nature of network interfaces.
2025-09-25 15:18:18 -04:00
Jarrod Johnson 3505fe36e6 Remove hiddenmenu
This no longer applies to most grub2
2025-09-25 14:07:27 -04:00
Jarrod Johnson 29accaa494 Change grub to not prompt
Sometimes grub can get stuck unexpectedly waiting for interaction. Try to get away from this by default
by setting the timeout to 0.
2025-09-25 10:09:25 -04:00
Jarrod Johnson f66093680b Attempt to loop on reconfiguring networking
This may induce DHCP to be retried
2025-09-25 10:08:05 -04:00
Jarrod Johnson 97d4015b09 Handle memory inventory without type indicated 2025-09-22 15:21:53 -04:00
Jarrod Johnson 184132c398 Fix collective manager candidates not in nodelist
For switch operations, need to carry over the same logic as other evaluations.
2025-09-19 19:41:54 -04:00
Jarrod Johnson ac7fdb3ef7 Enhance message for enclosure based discovery
If nodes are accidentally omitted, but present, provide a hint that may clarify
the situation.
2025-09-19 15:46:18 -04:00
Jarrod Johnson d7879bad5b Improve robustness of Ubuntu net bringup
If using DHCP, have the loop to validate connectivity repeat.
2025-09-19 15:44:55 -04:00
Jarrod Johnson 8911193aca Implement a test with retry for basic communication
confuesbox is likely to be a very early utility, and the relevant network is at high risk of being merely 'partially' up.
2025-09-19 11:50:12 -04:00
Jarrod Johnson e7e8daafea Merge pull request #198 from henglikuang/logdirectory
An effort was made at one point to have log directory configurable, but no way was actually done
to make it accessible.

This corrects that.
2025-09-18 15:19:07 -04:00
Jarrod Johnson 3f9a13ed6f Ensure certfile is blanked before writing to it 2025-09-18 15:14:39 -04:00
Jarrod Johnson 500cdf7535 Change boot.img to boot.iso for Windows
Some things expect an iso to be named as such. This drives different handling, but
there's little choice in the matter.
2025-09-18 08:55:09 -04:00
Jarrod Johnson 22c8921455 Place identity files loose in directory as well
Some OS deployment mechanism may wish to convey the identity information more loosely. For those, it's convenient if the files are loose instead
of needing extraction from a VFAT image.
2025-09-17 09:25:40 -04:00
Jarrod Johnson ebcf7d7bf8 Refresh genesis build version 2025-09-15 11:21:03 -04:00
Jarrod Johnson 7a2cb80f6a Make hmac import optional
Some environments do not have this module
2025-09-12 16:57:37 -04:00
Jarrod Johnson dd2b7be2ca Bump genesis version 2025-09-12 16:15:00 -04:00
Jarrod Johnson 678bd6052a Correct path to util-linux in genesis build 2025-09-12 15:59:48 -04:00
Jarrod Johnson cb5fcf077a Fix incorrect character in release filename 2025-09-12 08:50:32 -04:00
Jarrod Johnson 5f26fb73e6 Enable apiclient to be more self-sufficient
Provide a totally 'clortho' and 'copernicus' free behavior.

This allows some flows to skip the cpio addons to go straight to python.

Some scenarios demand the utilities (initramfs) and others are more awkward with the utilities,
so we enable both.
2025-09-09 16:47:44 -04:00
Jarrod Johnson c9ca199b16 Fix preference of netplan
If netplan and nmcli both exist, the intent was to prefer netplan.

However, there was a mistake that caused nmcli to be the most preferred.
2025-09-09 11:17:26 -04:00
Jarrod Johnson 8109adaabf Add BFB recognition to osimage parsing
Recognize BFB embedded OS as a potential osdeploy target.

This is toward the end of identifying the appropriate 'addons.cpio' for setting up for a bf.cfg driven bfb install.

For now, it is disabled until companion os category exists.
2025-09-04 15:23:03 -04:00
Jarrod Johnson 29c6ce230f Tolerate updateboot failure on first import 2025-09-04 10:21:01 -04:00
Jarrod Johnson 87a6891eff Include boot filename in ARM case
ARM PXE solutions often fail to properly implement
PXE, workaround by going ahead and including the boot filename.
2025-09-03 09:09:21 -04:00
Jarrod Johnson a112297e60 Detect ESXi editions for more specific fingerprinting 2025-09-02 10:19:41 -04:00
Jarrod Johnson c567bfbd17 Add sysctl tune check to selfcheck
Apart frem the gc_thresh indirect check, perform other checks.

For now, just highlight that tcp_sack being disabled can really
mess with BMC connections.  Since the management node may have high speed and the BMC may be behind a 100MBit link, SACK
is needed to overcome the massive loss and
induce TCP to rate limit appropriately.
2025-09-02 08:53:55 -04:00
Jarrod Johnson 6d2146f252 Provide more category based firmware query
Some platforms can have a very slow category,
like disks. Give CLI a way to ask for the desired
categories and a chance to optimize away the uninteresting.
2025-08-29 17:12:36 -04:00
Jarrod Johnson 5045b46014 Switch to ISO based boot for windows
Windows boot loader can be easily confused by a plurality
of vfat volumes, coddle it by giving it an ISO image for now.
2025-08-28 15:14:02 -04:00
Jarrod Johnson 5905510a32 Move tmp script execution out of /tmp
Some environments want noexec on /tmp, this will work in such environments.
2025-08-28 08:34:07 -04:00
Jarrod Johnson f321f56109 Make more windows content executable
Other files use the executable
bit as an indication of whether to run or not.
2025-08-28 08:08:30 -04:00
Jarrod Johnson 9defc47474 Give pycdlib a duped filehandle
Attempts to share the filehandle resulted in race conditions around closing,
dedicate a dupe filehandle to pycdlib to avoid the conflict.
2025-08-27 12:29:19 -04:00
Jarrod Johnson 595b628e08 Validate that the agent socket actually works
If agent is 'kill -9', then recover
from that by reaping the now dead socket.
2025-08-26 14:00:36 -04:00
Jarrod Johnson 710b24e9f5 Recover from dead ssh agent
If the ssh-agent is gone, for whatever reason, restart it.
2025-08-26 11:10:43 -04:00
Jarrod Johnson c26fba74e7 Fix issues with EL10 installtodisk 2025-08-26 09:52:21 -04:00
Jarrod Johnson a01eb64adc Remove disused function from confluent2ansible 2025-08-26 09:50:25 -04:00
Jarrod Johnson ac8179b867 Amend swraid example script 2025-08-26 09:49:28 -04:00
Jarrod Johnson 87990c72c3 Make EL10 diskless consistent with EL9 2025-08-26 09:06:28 -04:00
Jarrod Johnson a6a57e8590 Fix ssh operation during install in installtodisk for el9 2025-08-26 08:59:10 -04:00
Jarrod Johnson 6be98c7e60 Fix leaking ssh-agent processes in selfcheck 2025-08-26 08:44:42 -04:00
Jarrod Johnson 1a64768fca Carry forward EL* installtodisk to EL9 2025-08-26 08:08:24 -04:00
Jarrod Johnson 157641e37a Fixup imported windows media
Samba by default needs executable bit on files for them to be executable by windows.

Only give executable bits to .exe files that are PE32, mitigating the chance the executable bit could mean anything for Linux.
It could still mean something with binfmt misc hooks, but that shouldn't be done much.
2025-08-25 08:59:53 -04:00
Jarrod Johnson 63bbe53448 Address numerous issues with 'installtodisk' for el8
Add missing pre.d directory to let user know they can use such scripts

Preserve console directievs from kernelargs into installed system

Retry umount during image2disk, if processes have the filesystem busy.

Fix DNS behavior during post phase of installtodisk

Invoke confignet properly during firstboot to set up additional interfaces.

Have sshd run during the install from '/sysroot', for convenience

Fix some cosmetic error output for setupssh
2025-08-22 08:39:40 -04:00
Jarrod Johnson ec3fcee7d7 Implement updateboot for windows profiles 2025-08-20 20:15:05 -04:00
Jarrod Johnson b2b2b5710b Fix up monolithing sshd_config for platforms that need it 2025-08-20 11:26:41 -04:00
Jarrod Johnson b32ded9c6a Fix skipping of quotation in grub config 2025-08-20 10:31:59 -04:00
Jarrod Johnson 75c228dae4 Fix syntax mistake 2025-08-20 10:10:01 -04:00
Jarrod Johnson afd2b6c219 Add storage drivers to imgutil for el8 diskless 2025-08-20 10:04:13 -04:00
Jarrod Johnson 9a85b9ee94 Fixes for installtodisk for diskless for el9 2025-08-20 09:55:26 -04:00
Jarrod Johnson c9c5165245 Fix syntax error in commit 2025-08-20 08:53:55 -04:00
Jarrod Johnson d4e91b1c7e Back port installtodisk to el8 diskless 2025-08-20 08:49:11 -04:00
Jarrod Johnson 98e78dd43c Reduce size of presumed diskless image for installtodisk
A diskless image is likely to be significantly smaller, have it support install
to smaller disks.
2025-08-18 16:34:26 -04:00
Jarrod Johnson e7606e69bd Wait for redfish account service to be ready before modifying users
If an XCC is booting, it may appear before it's ready to use redfish to manage user accounts.  Handle this by delaying the discovery until
the service is ready.
2025-08-15 10:18:49 -04:00
Jarrod Johnson 580c451945 Explicitly restart sshd on completion
Some changes from setupssh may require sshd restart, perform it
if running with the sshd unit running.
2025-08-14 07:24:28 -04:00
Jarrod Johnson a71804a13b Fix suse/ubuntu paths for apache config 2025-08-12 11:47:39 -04:00
Jarrod Johnson dbda4f45a1 Add 'proxmox' to valid values for console options 2025-08-12 10:49:01 -04:00
Jarrod Johnson 5ac0cccc4d Update proxmoxve for trixie
Have the proxmox post script adaptive between Debian 12 or 13
2025-08-11 17:11:18 -04:00
Jarrod Johnson 465e985cc7 Extract and use HWE by default for Ubuntu 24.04 2025-08-11 13:55:36 -04:00
Jarrod Johnson 836b629986 Remove unused json import from apiclient 2025-08-11 12:31:44 -04:00
Jarrod Johnson 58b6a2d317 Fix python2 incompatibility with apiclient 2025-08-11 12:20:10 -04:00
Jarrod Johnson fc6c1495d3 Change comment to not have unicode
Some environments don't like the UTF
2025-08-11 12:10:33 -04:00
Jarrod Johnson c9b9275bb1 Support clear of custom attributes
middle name attributes and custom attributes should
be checked for explicitly during a clear.
2025-08-11 11:46:35 -04:00
Jarrod Johnson c0a99f63a5 Correct typo in rpm spec changes 2025-08-11 10:31:55 -04:00
Jarrod Johnson 51afcc68a7 Add debian 13 support
Debian 13 changes the installer initramfs
to have lib be under usr, compensate.
2025-08-11 10:14:05 -04:00
Jarrod Johnson 902ff43a9b Extend certificate management
Provide checks for nginx config and apache configuration, perhaps even concurrently.

Latch on the first match, since we are taking care of IP based SANs and subsequent server/virtualhost sections are irrelevant.

Latch onto a chain file, if indicated in the apache configuration, placing our CA in the chain.

For nginx, put our CA in the cert, since nginx
uses the 'certificate' file as the chain.

In this scenario, a cross-signed CA cert is possible.
2025-08-08 17:27:26 -04:00
Jarrod Johnson e01701bcf1 Speed up log initialization
Cache the directory list over a few seconds
to avoid excessive filesystem calls.

Also switchg to a more potent regex to avoid wasting time on timestamped files.
2025-08-08 15:51:45 -04:00
Jarrod Johnson a1cf8023c6 Clarify that nodesensors csv may have a different order
CSV must keep sensors grouped and consistent, so it waits until it gathers
all results to sort.

Normally, it presents the results as quickly as the API provides it.

This results in some different ordering for the "fast as API provides it"
versus "delayed to group the values together" behavior.
2025-08-08 14:30:30 -04:00
Jarrod Johnson 960a890530 Fix discovery mac deletion to also clean associated node records 2025-08-07 15:15:14 -04:00
Jarrod Johnson d43de05b09 Present error when user tries to operate undefined PDU outlets 2025-08-07 14:56:12 -04:00
Jarrod Johnson 36ce0922fc Implement openEuler scripted install
openEuler 24.03 seems closest to el8, so start with that baseline.

Modify el8 handling to recognize a totally missing CA bundle and assume
the original el8 location.

Have osimage recognize openEuler media by presence of openEuler release file.
2025-08-06 14:56:12 -04:00
Jarrod Johnson aafa65274c Do not trip over .discinfo file contents 2025-08-06 14:27:05 -04:00
Jarrod Johnson 63bb5f4d1b Have routed diskless retry checking for interface
If the network interface is slow to link up, wait
until something comes up, ignoring infiniband for now.
2025-08-06 14:15:43 -04:00
Jarrod Johnson d99689f84b Have confluent2ansible support amending inventory
Rather than writing from scratch each time, parse the
existing file if present and merge new content without
perturbing existing.
2025-08-06 11:56:44 -04:00
Hengli Kuang 816f3be2ed Configure the logdirectory from the configuration file
- Set the log directory using the configuration manager
- Add _get_logdirectory function to retrieve the log directory path
- Update _redirectoutput to use the new log directory setting
2025-08-06 04:31:38 -04:00
Jarrod Johnson bab169269c Fix variable mistake in error handling 2025-08-05 08:39:18 -04:00
Jarrod Johnson 85ddf528a2 Add Confluent UUID to identity image
The UUID and tls material usually comes from site, but some
OSes may depend entirely on the identity image, so
make the UUID available that way as well.
2025-08-01 15:53:38 -04:00
Jarrod Johnson 8cfbf40a2e Implement capture of extra volume groups
Provide a mechanism to capture non-boot hosted volume groups
and map them to specified disks via a mapping.
2025-08-01 12:02:04 -04:00
Jarrod Johnson 48a0c21300 Refine getinstalldisk
Reduce obvious output about skipped devices.

Rule out any read-only device.

Amend minimum size to 2GB.

Among same priority devices, select the smallest target.
2025-08-01 09:00:25 -04:00
Jarrod Johnson 2c43055aec Amend handling of malformed bytes in output
Additionally, fix handling of mixed numeric/string in the attribute handler.
2025-07-31 08:44:58 -04:00
Jarrod Johnson 16a1c4d598 Pull mtu into the netcfg api 2025-07-29 15:45:41 -04:00
Jarrod Johnson 97e4d7c3d0 Skip sr0 if attempted 2025-07-29 15:33:05 -04:00
Jarrod Johnson cfa16237e1 Dismantle initramfs by default in EL9/EL10 diskless
If debugssh is not requsted, the initramfs is not needed.

Do not unshare the mount namespace, leave the kernel relevant namespace 'normal'

Remove some initramfs content to free up some memory.
2025-07-29 14:26:43 -04:00
Jarrod Johnson 7066f85520 Merge remote-tracking branch 'xcat' 2025-07-29 07:03:22 -04:00
Jarrod Johnson 8c6f36adf3 Fixes for ansible running
Newer ansible requires deferred plugin initialization explicitly,
support either ansible norm.

Reliably mark a play as complete even if facing a very early init
problem, e.g. if ansible shebang points to a non-existant python.

Fix incorrect association of stderr to tasks, and present
stderr to the client exactly once.
2025-07-28 15:55:16 -04:00
Jarrod Johnson 33cee4174e Merge pull request #196 from Obihoernchen/doclink
Update documentation link
2025-07-25 15:03:49 -04:00
Jarrod Johnson 47710756a5 Implement mtu for netplan backend 2025-07-25 15:01:26 -04:00
Jarrod Johnson 21429c6d7d Implement mtu for networkmanager backend 2025-07-25 14:48:03 -04:00
Jarrod Johnson ff0c11e919 Add mtu to net attributes 2025-07-25 14:47:46 -04:00
Jarrod Johnson bf209a8009 Explicitly recognize fe80::/64 as 'local'
For various reasons, it is likely/expected for fe80:: to fail the 'local'
check. This is fine in most contexts, except for credserver and ssdp.

ssdp already special cased fe80::, so special case fe80:: in credserver
as well.
2025-07-24 16:20:12 -04:00
Jarrod Johnson 6ec072be9d Fix EL10 for ARM nodes 2025-07-22 14:25:39 -04:00
Jarrod Johnson 79e44e420a Fix console handling for vcenter and proxmox plugins 2025-07-22 09:26:50 -04:00
Markus Hilger 5a0b2468f6 Update documentation link 2025-07-11 03:08:50 +02:00
Jarrod Johnson 13d9fe2712 Revert useinsecureprotocols to any group value after adoption 2025-07-02 09:55:24 -04:00
Jarrod Johnson 5028ed9f07 Avoid set changed during iteration 2025-07-01 15:45:24 -04:00
Jarrod Johnson 05dbbd6ce0 Explicitly check root user keys
Replace simple existence check
with a check that assures the content also matches.
2025-06-25 16:10:26 -04:00
Jarrod Johnson 61749c3649 Support older Pillow libraries
Some distributions bundle older pillow, and we have
a way to support them.
2025-06-25 13:47:29 -04:00
Jarrod Johnson 1f3b84cc9d Implement Windows iso extraction
If a user has custom
windows categories, match
them to media import.

To do this, we needed to go to pycdlib, as libarchive can't
do UDF-only isos.

For now, this has no progress indication, but does extract it similar
to most Linux distributions are done.
2025-06-24 16:32:31 -04:00
Jarrod Johnson ac42c1b4c7 Skip IPv6 lookups on IPv4 context
For DHCPv4 context, it makes no sense to bother with IPv6 addresses that cannot be used.
2025-06-24 13:40:40 -04:00
Jarrod Johnson e489d2d532 Fix setupssh behavior on nearly full /tmp/ 2025-06-18 08:55:13 -04:00
Jarrod Johnson 7bde5c4291 Fix netifaces fallback
If psutil is not available, continue with netifaces as before
2025-06-17 15:43:15 -04:00
Jarrod Johnson 4009aa1aa1 Query the BMC rather than the SMM itself 2025-06-17 15:13:31 -04:00
Jarrod Johnson 935691d1f3 Fix util for pre-psutil distributions 2025-06-17 14:20:17 -04:00
Jarrod Johnson 7fd9a207b1 Switch el10 to el9 binaries for diskless
The libcrypt change has to be accommodated
2025-06-17 10:58:54 -04:00
Jarrod Johnson 551862e85e Only start ssh if requested on cmdline 2025-06-17 10:53:55 -04:00
Jarrod Johnson a36040fa92 Include el10 imgutil contents 2025-06-17 10:39:34 -04:00
Jarrod Johnson b74732ecfa Change to symlinks for most of el10 diskless
Most is common with el9
2025-06-17 10:30:49 -04:00
Jarrod Johnson bb7e0d1d1e Correct mistake in the previous commit 2025-06-17 10:27:40 -04:00
Jarrod Johnson cb1f06fecf Add EL10 Diskless 2025-06-17 10:14:09 -04:00
Jarrod Johnson dcd59667e4 Add a secondary copernicus loop to diskless
Sometimes 30 seconds just isn't enough.
2025-06-11 16:19:13 -04:00
Jarrod Johnson 5a96c7a20c Change to grep -E
This avoids a obsolescence message in rpm update
2025-06-11 15:57:39 -04:00
Jarrod Johnson 7d49c5f9be Do not error out on listing profiles/distributions before any exist 2025-06-11 15:48:53 -04:00
Jarrod Johnson 0ec5cf5c5e Make the keysign pre script readable 2025-06-11 15:48:23 -04:00
Jarrod Johnson 6b94a8fa22 Add openssh-keysign to el10 distributions 2025-06-11 15:19:52 -04:00
Jarrod Johnson 45fa229f9f Reduce columns to fit in X tiling
Check if right side of window will fit instead of
left side.
2025-06-11 14:24:25 -04:00
Jarrod Johnson 071433a60a Handle underscore in volume name
Only the first underscore would be in the volume groub name,
the rest would be a part of the volume name, which should be
excluded.
2025-06-11 08:00:58 -04:00
Jarrod Johnson 7dd5c36e78 Remove EL7, add EL10 to the spec for imgutil 2025-06-10 13:25:15 -04:00
Jarrod Johnson 26f3ee539f Add el10 to imgutil spec 2025-06-10 13:01:08 -04:00
Jarrod Johnson dcfb028ba9 Add popular virtual machine storage drivers to imgutil 2025-06-09 15:57:02 -04:00
Jarrod Johnson 59dc7b5426 Fix another error in the psutils work 2025-06-09 14:45:43 -04:00
Jarrod Johnson 65b613219e Amend mistake in previous commit 2025-06-09 14:33:12 -04:00
Jarrod Johnson c7d41f8a4b Support and prefer psutil
The netifaces library seems dead, we can use psutil instead
which seems more popular.
2025-06-09 14:12:31 -04:00
Jarrod Johnson 5f9250c492 Add el10 clause 2025-06-06 20:14:07 -04:00
Jarrod Johnson 169fd976ce Compensate for out of sync resize behavior
During the async vnc behavior, a copy of the geometry variables
are used that are out of sync.

Workaround by forcing a resize again after the async tasks conclude.
2025-06-06 10:56:50 -04:00
Jarrod Johnson d063f50a9c Fix a possible breakage due to transmit error
SSDP snoop could have been brought down by
a non-viable transmit, tolerate that failure.
2025-06-06 10:52:27 -04:00
Jarrod Johnson 6a90e1cc77 Implement a VNC to screenshot
For Proxmox, since no convenient screenshot mechanism is available,
instead do vnc.
2025-05-30 16:26:34 -04:00
Jarrod Johnson 7aaa350679 Fix missing import from stats 2025-05-30 15:48:32 -04:00
Jarrod Johnson a1a144d211 Implement plugin managed VNC
To extend beyond the OpenBmc wrapped dialect of VNC,
provide mechanism for plugins to provide
arbitrary cookie, password, url, and protocols parameters.

Implement for ProxMox.
2025-05-30 15:48:15 -04:00
Jarrod Johnson 8d8db070eb Fix mistake in ctypes call in userutil 2025-05-30 15:19:42 -04:00
Jarrod Johnson 4fd7021581 Add EL10 distributions 2025-05-28 11:15:22 -04:00
Jarrod Johnson 250de6133d Stop trying to save a fingerprint that didn't exist 2025-05-27 15:46:29 -04:00
Jarrod Johnson 40f3ca73c4 Fix mistake in RHEL10 recognition commit 2025-05-22 16:59:16 -04:00
Jarrod Johnson 19c4dc71db Add recognition of RHEL10 media 2025-05-22 14:30:58 -04:00
Jarrod Johnson 94dc266cd4 Add neighbor overflow check to confluent_selfcheck
A common issue in larger layer 2 configurations is
for the neighbor table to be undersized for the number of
nodes.

Detect this manifesting and present a message.
2025-05-22 13:57:16 -04:00
Jarrod Johnson 1a679ab6eb Improvements to nodediscover
For one, understand 'ip' to potentially mean 'bmc' for list
to assign convenience.

Parallelize handling of csv importing to improve performance.

Only call rescan once per bulk assign
2025-05-22 13:45:39 -04:00
Jarrod Johnson 8722e66583 Try a different dev build versioning
Python 3.12 refuses to use the current versioning
2025-05-21 10:00:47 -04:00
Jarrod Johnson 6bebae1d0b Switch several node commands to epoll
Improve ability to handle high fanout amounts by
using epoll instead of select.
2025-05-20 10:39:57 -04:00
Jarrod Johnson 11939c4d57 Preserve aspect ratio if Pillow available
Since we are controlling the scaling, we can manage
things more precisely and get the aspect ratio right.
2025-05-16 09:44:57 -04:00
Jarrod Johnson ee53ee47c1 Fix loss of uppercase during reverse noderange
Reverse noderang was changing names to lower case,
fix to preserve case.
2025-05-15 16:30:12 -04:00
Jarrod Johnson 8111a13554 Reuse image preprocessing for iterm and kitty
Both can benefit, and lets iterm handling scale the way
we would like to scale it.
2025-05-15 11:00:44 -04:00
Jarrod Johnson ef46b6cabd Take ownership of image scaling
This fixes the imposed border being mangled, and also allows
Konsole to present decent looking scaling since it no longer
has to scale.
2025-05-15 10:00:03 -04:00
Jarrod Johnson 08738713c9 Handle NLMSG_DONE wherever it may appear in reply
Some kernels may bundle the NLMSG_DONE in the last
useful system call, unlike the previous norm of sending it as
a single message in a terminating system call.
2025-05-15 08:39:45 -04:00
Jarrod Johnson 7cb6b1ac35 Fix autoconsole error on SPCR-free EFI implementations 2025-05-13 16:46:18 -04:00
Jarrod Johnson 315d1d9b5e Change to common image from text for errors
This allows easier management of rendering of text.

Also add a black and white border to make tiling more delineated.
2025-05-13 15:39:40 -04:00
Jarrod Johnson d382bd5182 Provide cleaner recovery for image decode failure
When doing the kitty support with pillow installed,
recover from a condition, creating a stub 'screenshot' to
reflect the error.
2025-05-13 14:23:38 -04:00
Jarrod Johnson fca0119331 Amend URL shortening
302 works for iPXE, but not for more limited UEFI
http client.

If we are dealing with UefiHttpBoot, check for a header
from nginx config and use X-Accel-Redirect to induce proxy side
redirect transparent to client.

Otherwise, give an error indicating the issue with the profile
name length and incompatibility with Apache capabilities.
2025-05-13 11:41:11 -04:00
Jarrod Johnson a7c338786e Fix dotted field names in stub formatter
The stub formatter was chocking on dotted
key names.
2025-05-09 16:39:45 -04:00
Jarrod Johnson c892af5a1e Implement 8 character max for attribute formatting
When trying to set a node or group attribute, evaluate
length of any potential formatting specification to keep it under
8 characters.

This should prevent even temporary expansion over 10MB for an attribute
on the way to setting it.
2025-05-09 09:34:19 -04:00
Jarrod Johnson 870cee5ed8 Add public TLS certificates to identitiy images
Some profiles may want to have a fixed boot image,
and site specific content limited to the identity payload, or at
least the TLS so it could fetch the rest over https.
2025-05-09 09:11:58 -04:00
Jarrod Johnson 76a66a46e1 Restrict maximum attribute size from formatting
If an expression causes an inordinate amount of memory to be
used, then block it from continuing.

For now, we consider that an expression that expands beyond 16k.  I
am unable to conceive of a use case where someone would want to
use an expression to derive more than 16k as it stands, as we don't
carry any particularly large opaque payloads right now.
2025-05-08 17:01:35 -04:00
Jarrod Johnson df354c2f7d Add some network drivers to cloning/diskless
The r8169 enjoys some popularity.

Also, we'd like to be able to try out diskless/cloning with
VMs, so vmxnet3 and virtio_net are handy to round that out.
2025-05-08 11:21:27 -04:00
Jarrod Johnson 5b1492fed8 Restore error message on chassis without location information. 2025-05-06 15:31:03 -04:00
Jarrod Johnson ca3a53fde4 Provide specific guidance for bad ssh key permissions 2025-05-06 09:51:11 -04:00
Jarrod Johnson 5ab16851ec Treat '' as equivalent to unset for ipv{}_method
Since it's a really difficult distiction between blank
and unset, make sure this is treated the same.
2025-05-06 09:01:43 -04:00
Jarrod Johnson febccf4d5e Fix imgutil with el8 diskless 2025-05-06 08:39:53 -04:00
Jarrod Johnson d0ae7b46ae Disable the HTML API explorer
It may be the case that no one uses it.
2025-05-02 16:21:47 -04:00
Jarrod Johnson 57ada3728c Change default host to localhost only
Also, fix support for IPv4 addresses as bind_host
2025-05-02 16:18:28 -04:00
Jarrod Johnson 89437ee761 Fix Proxmox sample scripts for post/firstboot 2025-05-02 13:19:56 -04:00
Jarrod Johnson bfadc284b0 Expand documentation of graphical nodeconsole usage. 2025-05-02 08:57:29 -04:00
Jarrod Johnson fbea510fc1 Have nodeconsole respond to resize
When doing the screenshot tiling with interval,
sanely handle resizing the terminal.
2025-05-01 12:13:27 -04:00
Jarrod Johnson 5be99d995a Fix up VM power handling
For both proxmox and vmware, properly model the 'oldstate' feature.

For proxmox, further:
- Wait for power change to actually take effect
- Change reset to a cycle, to help nodesetboot actually work correctly.
2025-05-01 11:44:35 -04:00
Jarrod Johnson b3ffd632a5 Add proxmox ve example scripts to debian profile 2025-05-01 10:23:42 -04:00
Jarrod Johnson 62988117f1 Another iteration toward debian bookworm support 2025-05-01 09:39:18 -04:00
Jarrod Johnson 71f5ce2b29 Add deployment lock mechanism
This allows users to opt into disabling setting further profile changes.

Nodes may be 'unlocked' (normal), 'autolock' (will lock on next
completion), or 'locked' (unable to change the pending OS profile)
2025-05-01 09:25:05 -04:00
Jarrod Johnson 0c0cac140d Add debian profile material
Implement Debian 12 installation
2025-04-30 17:06:20 -04:00
Jarrod Johnson 5cc70846fd Fix asymmetric ipv4/ipv6 attribute PXE response
If a nic were aliased *and* the node had attributes
for ipv6 but used host resolution for ipv4 identity,
it was possible for PXE to pick the wrong way
to respond.

Instruct netutil to specifically consider only the matching family
for the PXE/HTTP boot context
2025-04-30 15:54:46 -04:00
Jarrod Johnson 71f75dbc31 Provide specific error on empty noderanges for expressions
For commands such as nodeshell and noderun,
provide a more useful message when a noderange is empty.
2025-04-29 16:13:33 -04:00
Jarrod Johnson f797ede15f Handle 503 from a stopped confluent member
If a confluent collective member is stopped, then the
HTTPS check passes.  If we end up with a 503 indicating
the other end has a missing confluent, fall back to the loop
to check for other living collective members.
2025-04-29 15:44:13 -04:00
Jarrod Johnson 9b3c8e185d Merge remote-tracking branch 'xcat' 2025-04-29 10:23:20 -04:00
Jarrod Johnson 9fa5278204 Merge pull request #191 from tkucherera-lenovo/nodeconsole
document nodeconsole sreenshot feature
2025-04-29 10:22:37 -04:00
Jarrod Johnson fd4c2686a4 Add telnets support to vmware console
This allows the console to be credibly secured,
provided the current host is a node to hold the known hosts...
2025-04-29 10:19:08 -04:00
Tinashe d4d9b015b8 document nodeconsole 2025-04-29 09:54:43 -04:00
Jarrod Johnson 0b5be68586 Give media bootstrap more of a chance in genesis
If the USB is slow to enumerate, keep trying during the network
scan to let the USB have a chance to interject if the network
is unwilling.
2025-04-29 09:53:58 -04:00
Jarrod Johnson 80bf0c9bfa Clean up a relatively common potential error in XC scan
Do not clutter logs with this condition.
2025-04-29 09:53:19 -04:00
Jarrod Johnson f89cc5863f Add text console support for Proxmox guests 2025-04-29 09:52:47 -04:00
Jarrod Johnson 6552c90e4d Clean up busy loop and other oddity with vcenter console
Fix it so that common conditions do not
trigger trace logs and busy loops.
2025-04-29 09:52:19 -04:00
Jarrod Johnson 0e8a6038dc Merge remote-tracking branch 'xcat' 2025-04-28 19:10:37 -04:00
Jarrod Johnson 797b5fc478 Fix proxmox power reporting while off 2025-04-28 19:09:56 -04:00
Jarrod Johnson 4c90d431b6 Add preliminary proxmox node support 2025-04-28 17:17:24 -04:00
Jarrod Johnson 5e87b3ff48 Merge pull request #190 from tkucherera-lenovo/nodeconsole
make nodeconsole kill more consistent
2025-04-28 11:00:01 -04:00
Jarrod Johnson 2370cb0b0a Merge pull request #188 from tkucherera-lenovo/console-redirect
remove-consoleredirect
2025-04-28 10:59:18 -04:00
Jarrod Johnson 20b4f46699 Add screenshot ikvm to vcenter plugin 2025-04-27 10:32:28 -04:00
Jarrod Johnson 74355e5220 Implement partial telnet for VMWare
The vmware serial support demands more proper
telnet support, provide some support for negotiating
do/don't, will/won't opcodes.
2025-04-25 18:41:01 -04:00
Tinashe 3b46ccb5b1 make nodeconsole kill more consistent 2025-04-25 16:55:25 -04:00
Jarrod Johnson 85249ae71b Basic VCenter plugin
This provides nodeinventory (mac and -s most interestingly),
nodepower, nodesetboot (and by extension, nodedeploy -n),
and nodeconsole (console.method=vcenter).
2025-04-25 13:19:38 -04:00
Jarrod Johnson 0bdcaecf82 Do not include localhost in syncfiles consideration
localhost was added to ssh principals, but should not be used
as a candidate in syncfiles.

The syncfileclient should already be filtering this possibility,
but best to filter it everywhere that makes sense.
2025-04-25 08:57:50 -04:00
Jarrod Johnson b4ef1b484a Amend syncfiles address selection.
A node with private, unroutable addresses relative to
the deployment server may cause the deployment server
to select an unroutable address.

Address this with two strategies.

First, if any of the addresses appear local to the deployment server
networks, prefer those and filter out unroutable.

Secondly, if a node is purely remote, and thus all addresses routable,
then make all the addresses a candidate. However, since the
client can't possibly be using fe80::, we can replace the principal list
with just the clientip, provided it appears in the principal list.
2025-04-25 08:55:10 -04:00
Jarrod Johnson 9f51e256ce Activate vinz on access if doing collective
If a node has not been asked to open any locally managed
video consoles before it was asked to open a peer managed console,
it would fail to start the needed vinz service.

Work around this by detecting that scenario and giving
the vinz subsystem a chance to fix itself.
2025-04-24 08:08:27 -04:00
Jarrod Johnson 1e1b7871cb Merge pull request #98 from weragrzeda/master
NTP servers fix for stateless images for RHEL 7-9
2025-04-24 08:05:55 -04:00
Wera Grzeda 1553af0f41 NTP servers fix for stateless images for RHEL 7-9
Node attribute ntp.servers in nodeattrib ca now be used in stateless images

	modified:   confluent_osdeploy/el7-diskless/profiles/default/scripts/onboot.sh
	modified:   confluent_osdeploy/el8-diskless/profiles/default/scripts/onboot.sh
	modified:   confluent_osdeploy/el9-diskless/profiles/default/scripts/onboot.sh
2025-04-24 10:47:38 +02:00
Jarrod Johnson 0c8799f4dd Favor more utilization of bottom screenshot row
When we have the grid size, cut off any extra columns
so long as it doesn't gain a row.
2025-04-23 12:50:44 -04:00
Jarrod Johnson 52b0ae179e Background console disconnect on node removal 2025-04-23 12:33:40 -04:00
Jarrod Johnson 690980c064 Always specify miimon=100 in networkmanager bonds
We already do this for SUSE, it makes sense as a default.
2025-04-23 10:28:42 -04:00
Jarrod Johnson 977d272c56 Fix untiled nodeconsole screenshot 2025-04-23 09:55:45 -04:00
Jarrod Johnson b5540dd395 Hide cursor during screenshot run 2025-04-23 09:48:54 -04:00
Jarrod Johnson af1659dafd Have nodeconsole exit below screenshots 2025-04-23 09:44:10 -04:00
Jarrod Johnson a69113222f Fix positioning errors in tiled console display
It turns out that specifying height and width explicitly
does not guarantee that the image protocols will actually fill
the specified space. Notably iterm will honor aspect ratio
(which is good), but leave the cursor where the image would
naturally leave it (which is difficult with relative positioning).

Previously, relative positioning was used as a workaround
for the fact that save/restore or any absolute positioning may
be fouled by incurring scroll.

To make cursor save/restore work, we determine the total rows and
print newlines enough to incur scroll and then move cursor back up.
This lets us use save/restore to ignore cursor movement by the image.
2025-04-23 09:34:44 -04:00
Jarrod Johnson 05ffc9da10 Constrain aspect ratio
When parceling out the screen real estate, avoid either the height
or the width from getting way out of proportion.

Better to let screen be unused than abuse it to distort the
aspect ratio too much.
2025-04-22 16:01:26 -04:00
Jarrod Johnson bfdd6a56f6 Add iterm tiling support
Also, block sixel attempts, since that is not implemented.
2025-04-22 10:58:25 -04:00
Jarrod Johnson 94af42031e Provide screenshot tiling with interval support
Only for kitty graphics protocol.

Also, attempt to use pillow to convert, if available.  Kitty itself
needs this, Konsole can work either way.

It currently does not preserve aspect ratio, to do that
we pretty much need to do some work with pillow.

If we specify just the height, then ratio is preserved, but it won't
honor the designed bounding box on wide screenshots. Also
Konsole won't even honor just one scaling factor.

So the better thing would be to determine the aspect ratio, which
needs pillow.
2025-04-22 10:35:14 -04:00
Jarrod Johnson 0cfdfbdfa4 Add tar.zstd capability
zstd is much faster and not too much bigger than xz
2025-04-18 11:19:12 -04:00
Tinashe 999a9c3acf remove-consoleredirect 2025-04-17 15:34:45 -04:00
Jarrod Johnson 082a20f776 Add mechanism to refresh screenshot in nodeconsole
For a single node, provide a way to cleanly
redraw a screen to keep an eye on it.
2025-04-17 10:34:11 -04:00
Jarrod Johnson 69240ef492 Add Fedora 42 scripted install support 2025-04-17 08:30:20 -04:00
Jarrod Johnson 656dea0929 Add error for failure to get screenshot
Usually this is due to the target not having a license key,
in the case of Lenovo equipment.
2025-04-16 15:34:06 -04:00
Jarrod Johnson e46b4ede6d Implement a CONFLUENT_IMAGE_PROTOCOL env variable
This directs CLI with image output to use a preferred protocol.

This is retroactively applied to stats.

Currently we prefer kitty, as it seems to be the most widely supported.

Though some things only support iterm, so that's an option.

And some only support sixel, but the user has to be the one to
figure out adding pysixel dependency.
2025-04-16 12:50:59 -04:00
Jarrod Johnson 9823ffc12d Fix collective serialization of screenshot messages 2025-04-16 09:46:48 -04:00
Jarrod Johnson e5da8c01a9 Do not attempt to print non-existent data. 2025-04-15 15:51:12 -04:00
Jarrod Johnson a138bef551 Do not worry about failure to reply to a SSDP confluent request 2025-04-15 15:40:17 -04:00
Jarrod Johnson e27f07ac36 Use IPv4 address for ikvm when fe80 is the local bmc
The fe80:: is hopeless, try to send ipv4 just in case.

Technically speaking, the user may be using a different address
or real ipv6 and the ipv4 guess might fail, but it probably won't.
2025-04-15 14:25:03 -04:00
Jarrod Johnson f11473c736 Numerous fixes for shell server
On exit, clear the terminal buffer and invalidate the session.  This
avoids the web ui being very attached to a closed, dead session, and
leaking stale buffer to a reused sessionid.

For confetty, treat starting a shell session more like starting a
console session.

If an attempt to resize a dead session is attempted,
ignore failures.
2025-04-14 10:25:25 -04:00
Jarrod Johnson 35e3ca1f1f Have screenshots become normal text
Base64 comes out as ASCII bytes, change to text for
json handling.
2025-04-14 07:53:40 -04:00
Jarrod Johnson 6d1da85991 Implement screenshot via nodeconsole -s
This will grab screenshots from Lenovo systems and
output them to the console, using the kitty image protocol.
2025-04-11 17:13:19 -04:00
Jarrod Johnson 507e6fa9ac Ensure bash runs the genesis_bootstrap from media 2025-04-11 16:05:08 -04:00
Jarrod Johnson e9372a4d34 Provide means for nodeping to use original name on -s 2025-04-11 15:10:28 -04:00
Jarrod Johnson 49ac3487c2 Fix bad indentation in add_local_repositories 2025-04-11 13:23:45 -04:00
Jarrod Johnson 1ec08336e6 Add notation on how to opt out of ubuntu install internet connect 2025-04-11 13:18:41 -04:00
Jarrod Johnson 90f4a2a062 Improve text console behaviors of Ubuntu and RedHat
RedHat makes grub redundantly handle serial output that firmware
already handles.  If we detect EFI firmware and SPCR ACPI table and
connected serial port, that suggests that firmware will handle.

Ubuntu hates serial console by default, amend it so it can actually
work for serial users.
2025-04-11 12:55:01 -04:00
Jarrod Johnson 1985525cc0 Add all gpgkeys to local repositories
gpgkey can take multiple, and better to specify them all instead
of just one.
2025-04-11 12:13:30 -04:00
Jarrod Johnson 9174ad651f Fallback to mac
Some systems do not have UUIDs. Which is unfortunate, but usually
a system mac address does well enough.
2025-04-11 08:38:51 -04:00
Jarrod Johnson ddf9244514 Correct typo in add_local_repositories 2025-04-09 17:00:56 -04:00
Jarrod Johnson 5e72a8b3c0 Handle reseat with '1a/1b' type bay description
This fixes ability to reseat newer chassis when
using the coordinate specification for bay location.
2025-04-09 16:29:57 -04:00
Jarrod Johnson 66265d170a Catch general reseat errors 2025-04-09 16:06:12 -04:00
Jarrod Johnson 2e60ca13b7 Try to add gpgkey to local repository
This is needed for things like followup imgutil
2025-04-09 13:27:29 -04:00
Jarrod Johnson 9744e0d1b0 Accept XCC and BMC for aliases of each other 2025-04-09 12:19:16 -04:00
Jarrod Johnson 7001f0d827 Add encoding for vfat usage in ubuntu genesis 2025-04-09 09:49:10 -04:00
Jarrod Johnson a6afbeebe0 Merge pull request #185 from Obihoernchen/validvalues_man
Show valid values from attributes.py in man pages
2025-04-09 09:13:10 -04:00
Markus Hilger 699efd2f4f Show valid values from attributes.py in man pages 2025-04-09 03:28:15 +02:00
Jarrod Johnson 5d60a6a427 Fix indentation in pdu module 2025-04-08 14:53:36 -04:00
Jarrod Johnson 672bc73756 Fix for potential hangs on race condition with task exit 2025-04-08 14:10:40 -04:00
Jarrod Johnson 0e3543c4aa Fix elif clause in module-setup 2025-04-08 10:51:29 -04:00
Jarrod Johnson 43d9fe09cf Merge remote-tracking branch 'xcat' 2025-04-08 10:44:05 -04:00
Jarrod Johnson 9cc3c96f6a Fetch fingerprint before credentials
Some implementations choose to close the certificate command after
granting user/password. Make sure we get the certificate first.
2025-04-08 10:40:07 -04:00
Jarrod Johnson b3b852a9e1 Add Ubuntu GUI considerations for genesis 2025-04-08 10:39:35 -04:00
Jarrod Johnson 71ddbb88fc If doing GUI in Genesis, defer until after udevd
udev is needed to run in some scenarios for seatd/sway to
function correctly.
2025-04-08 09:25:19 -04:00
Jarrod Johnson 5df6f9adbf Merge pull request #184 from tkucherera-lenovo/console-redirect
seperate console redirect scripts into oses
2025-04-07 15:19:03 -04:00
Jarrod Johnson 799fff10ff Handle different locale layouts 2025-04-03 14:58:09 -04:00
Jarrod Johnson bf03d8dc82 Pull locale file into genesis build 2025-04-03 14:51:58 -04:00
Jarrod Johnson 65760bb678 Break locale to a separate file 2025-04-03 14:49:24 -04:00
Jarrod Johnson 9980414160 Hook gui in genesis build if detected 2025-04-03 14:30:25 -04:00
Jarrod Johnson 5f7a5b18bf Add Sway to genesis install assets 2025-04-03 14:28:25 -04:00
Jarrod Johnson 53760ac576 More changes to support debian genesis host 2025-04-03 13:11:56 -04:00
Jarrod Johnson 1fa2baacb7 Support debian style lib layout 2025-04-03 13:06:37 -04:00
Jarrod Johnson b1ba1720b9 Suppress scary message from apiclient when asked to just do -f. 2025-04-02 11:10:33 -04:00
Jarrod Johnson b21d8b75e0 Incorporate block device into retry loop
Have block devices checked for identity information
in a loop with network source search.

Block devices may be delayed for various reasons. The previous method
could be bypassed by fast block device cutting off slow device
enumeration. It also incurred a delay for the network install
case.
2025-04-02 09:50:15 -04:00
Jarrod Johnson df6818a3cc Fix refactoring of detect_backend to lldp module 2025-04-01 15:59:02 -04:00
Jarrod Johnson 98add92a20 Correct the path to the api key during ubuntu installation 2025-04-01 15:26:37 -04:00
Jarrod Johnson 85b19acf5f Fix NXAPI neighbor table API backend 2025-04-01 15:22:36 -04:00
Jarrod Johnson e5f588d2b7 Fixup work to add nxapi for neighbor api backend 2025-04-01 14:24:59 -04:00
Jarrod Johnson c8ed877fda Make clearer api grant errors 2025-04-01 14:05:46 -04:00
Jarrod Johnson b665365178 Start with esxi7 contents as base for esxi9 2025-04-01 08:18:51 -04:00
Jarrod Johnson 48921c4ef0 Quick scanner to do ssdp scan 2025-03-31 15:12:29 -04:00
Jarrod Johnson df2c6a4e18 Fix states of absent PSU in NX-API 2025-03-28 17:30:49 -04:00
Jarrod Johnson 92ac49b561 Add NXAPI backend for mac table support. 2025-03-28 17:28:42 -04:00
Jarrod Johnson 2514507b87 Add node operations against Nexus switch
This enables the commands to work that one would expect.
2025-03-28 13:34:03 -04:00
Jarrod Johnson 7419dbcf71 Fix unpatched imports of webclient 2025-03-28 09:26:41 -04:00
Jarrod Johnson 659f87877d Rename the NX-API library 2025-03-28 08:29:18 -04:00
Jarrod Johnson 586261ddca Fix messed up PSU in nxos 2025-03-27 16:42:28 -04:00
Jarrod Johnson fc0cc41b90 Commence work on NXAPI support 2025-03-27 16:37:25 -04:00
Tinashe b596de93a0 seperate into oses 2025-03-27 11:09:25 -04:00
Jarrod Johnson ce5c1c925e Adapt to register XCC3
Handle XCC3 differences in the register scenario.
2025-03-27 10:00:44 -04:00
Jarrod Johnson 72c030995f Tolerate errors during register
If a condition breaks unicast query, keep going.
2025-03-27 09:50:19 -04:00
Jarrod Johnson 4677f2c806 Bump genesis version for next release 2025-03-25 11:20:58 -04:00
Jarrod Johnson 401ac50730 Merge remote-tracking branch 'xcat' 2025-03-25 11:20:40 -04:00
Jarrod Johnson 249ed5d9be Add script to try to sort out extra license material 2025-03-25 11:19:38 -04:00
Jarrod Johnson c29c9d5c47 Merge pull request #183 from stoderica/esxi7_fix
Modify apiclient utility, for esxi7 only, to check if the uplink of v…
2025-03-25 07:54:34 -04:00
Sorin Toderica 62e081cd72 Modify apiclient utility, for esxi7 only, to check if the uplink of vSwitch0 is up and if not, to try to replaces it with a different vmnic, that is up 2025-03-25 09:50:40 +02:00
Jarrod Johnson 1cf2a5339a Move sftp server to a more appropriate location 2025-03-24 16:34:51 -04:00
Jarrod Johnson 5ab02c31ee Add python 3.13 option for genesis 2025-03-24 16:34:15 -04:00
Jarrod Johnson 21f4d2e5c2 Remove opa from genesis 2025-03-24 16:29:51 -04:00
Jarrod Johnson fae266bf61 Refresh genesis for 3.13 release 2025-03-24 16:28:36 -04:00
Jarrod Johnson 84881cc6be Fix invoke to a file to not repeat the request 2025-03-21 09:12:57 -04:00
Jarrod Johnson 24e419568a Remove spurious output from stdout log 2025-03-21 09:12:41 -04:00
Jarrod Johnson e375c956ed Provide command line access to the updatestatus 2025-03-20 09:32:30 -04:00
Jarrod Johnson f6e9691b7f Amend arguments on IPv4 invocation
It turns out that when busybox invokes openssl for
IPv4, it does not pass a servername field.

In this case, start amending arguments after '-verify' instead, to catch
the verify_ip argument correctly.
2025-03-20 08:21:47 -04:00
Jarrod Johnson 5fb04126e6 Fix tracking of 'active' updates in update status 2025-03-19 16:43:19 -04:00
Jarrod Johnson 02bd26e7d2 Correct updatestatus to be resource, not collection 2025-03-19 16:17:31 -04:00
Jarrod Johnson 3a9b75839b Add another error code for XCC user rename refusal
Yet another error to reperesent rename refusal
2025-03-19 16:08:42 -04:00
Jarrod Johnson 29915acaeb Provide API to query update readyness 2025-03-19 15:31:51 -04:00
Jarrod Johnson ef68259745 Provide more full fixup of openssl invocation in wget
For IPv4 and IPv6, strip the ':443' for arguments where it doesn't make sense.

For IPv6, strip out [, ], and '%' from those arguments.
2025-03-19 12:41:50 -04:00
Jarrod Johnson e25b3acd98 Fix onboot.d in genesis profiles 2025-03-19 09:41:21 -04:00
Jarrod Johnson 1e463367fe Switch Ubunut initramfs to ssl
The busybox wget invocation of openssl is broken.

Override by stubbing it out to let openssl pick the verify
hostname instead of wget specified one, which is incorrect.
2025-03-18 15:52:37 -04:00
Jarrod Johnson 7d83a920a2 Add mechanism for configurable ikvm response
This allows for more flexible ikvm handling with newer pyghmi.
2025-03-13 15:59:10 -04:00
Jarrod Johnson 6402861f4c Provide custom node secret attributes
This allows for confluent to pass node secret data through.
2025-03-13 14:22:26 -04:00
Jarrod Johnson 0205f70d5a Merge pull request #182 from tkucherera-lenovo/eventlog
handle empty timestample
2025-03-13 10:22:39 -04:00
Jarrod Johnson 58608016c4 Add wait for disk bringup to allow media based co-opt of genesis 2025-03-12 13:23:00 -04:00
Tinashe 7d7baf0f77 handle empty timestample 2025-03-12 12:51:42 -04:00
Jarrod Johnson 9123d2f2e0 Add ability to post bodys to HTTP requests 2025-03-11 15:35:35 -04:00
Jarrod Johnson 9cecaab055 Fix confluent server identification using -s instead of file 2025-03-11 15:04:36 -04:00
Jarrod Johnson 9136341bda Tolerate different proxy pass configurations
The stock reverse proxy configuration strips the leading
'/confluent-api/' from the URL.

However, when doing a custom reverse proxy set up, one may preserve full
path without knowing which way to go.

Since '/confluent-api/' will never be used inside the api, just strip
it when detected to tolerate either of the likely proxy pass behaviors.
2025-03-11 11:38:05 -04:00
Jarrod Johnson d2011261ab Enable creation of bond and dependent tags in one iteration
Have a second pass to check interfaces that may
be created by the first pass.
2025-03-11 09:58:51 -04:00
Jarrod Johnson 060b81e205 Fix documentation error in attributes 2025-03-11 08:39:28 -04:00
Jarrod Johnson 1f97a5e67d Add a Makefile for building 2025-03-07 18:01:55 -05:00
Jarrod Johnson 13a6493100 Add a general utility for confluent in golang 2025-03-07 17:16:13 -05:00
Jarrod Johnson 28c929aec6 Have a draft apiclient in golang 2025-03-05 17:14:55 -05:00
Jarrod Johnson b4b011663e Handle more forms of confluent headers
Some frameworks won't allow headers through, normalize case
and normalize _ presence.
2025-03-05 17:14:28 -05:00
Jarrod Johnson defd41488e Merge remote-tracking branch 'xcat/master' 2025-03-05 13:13:55 -05:00
Jarrod Johnson 95952b5231 Detect active nic in multi-nic BMC discovery 2025-03-05 13:13:34 -05:00
Jarrod Johnson 857854a6e9 Merge pull request #179 from Obihoernchen/yaml
Implement YAML support for confluentdbutil (fixes #152)
2025-03-05 11:43:18 -05:00
Markus Hilger e5b1b5d3a0 Implement YAML support for confluentdbutil (fixes #152) 2025-03-05 17:42:31 +01:00
Jarrod Johnson c26936a2d7 Merge pull request #180 from Obihoernchen/fqdnfirst
Support FQDN first (Fix #167)
2025-03-05 11:35:36 -05:00
Jarrod Johnson 80ea0b3e91 Merge pull request #181 from tkucherera-lenovo/console-redirect
modify redirection code for rhel
2025-03-05 11:31:01 -05:00
Tinashe 1bfad11ee5 remove-mkconfig 2025-03-05 11:19:34 -05:00
Tinashe 7b4063a42f modify redirection code for rhel 2025-03-05 11:12:31 -05:00
Markus Hilger 2bc347fc2a Support FQDN first (Fix #167) 2025-03-05 04:17:45 +01:00
Jarrod Johnson f458c15677 Correct launching of GUI in genesis 2025-03-04 16:11:28 -05:00
Jarrod Johnson 02ec40092e Have genesis optionally GUI capable
Have Genesis work with newer distribution base, also support seatd/sway when
genesis contains it.
2025-03-04 15:12:59 -05:00
Jarrod Johnson cea87d012c Fix missing import from prepfish example. 2025-03-04 10:51:02 -05:00
Jarrod Johnson c73352a293 Add filter for bmc interface
People have been putting the BMC interface as
a net section, to aid in their information
and confluent2hosts.

Tolerate that by dropping net entries that match the
hardwaremanagement.manager attribute.
2025-03-04 10:50:48 -05:00
Jarrod Johnson f06d9a81e7 Have sshd only generate ed25519 during initramfs phase of diskless.
sshd-keygen service will come later with other keys, if desired.
2025-03-04 10:04:30 -05:00
Jarrod Johnson 0d4da78f05 Add certificate handling to prepfish.py 2025-03-03 10:51:10 -05:00
Jarrod Johnson 44a30686cb Add Fedora 41 scripted install support 2025-02-28 08:53:26 -05:00
Jarrod Johnson 596dca5d48 Merge pull request #178 from henglikuang/master
add a loop to find the accessible deployer when the method is not static
2025-02-28 06:36:07 -05:00
Hengli Kuang 75a0f44a36 add a loop to find the accessible deployer when the method is not static 2025-02-28 13:53:28 +08:00
Jarrod Johnson bde03f4595 Merge remote-tracking branch 'xcat' 2025-02-25 15:30:13 -05:00
Jarrod Johnson f62c0db678 Remove ssh_config directive not supported by EL7wq 2025-02-25 15:29:22 -05:00
Jarrod Johnson 132824ede5 Merge pull request #176 from tkucherera-lenovo/configbmc
Configbmc
2025-02-25 13:57:28 -05:00
Tinashe a595abe9e6 also allow users to just specify lom and we use the first port 2025-02-25 12:13:18 -05:00
Tinashe 11d63a4b5c allow users to choose which lom port to use for bmc shared mode 2025-02-25 11:00:16 -05:00
Jarrod Johnson 67bacc9934 Add sample script for bringing up a host interface 2025-02-21 15:25:41 -05:00
Jarrod Johnson 3a3f3a961d Add SMM3 to chained SMM logic 2025-02-20 15:42:49 -05:00
Jarrod Johnson 5fda02b9e0 Repeat NIC check loop on Ubuntu 18.04 deployments 2025-02-20 12:54:55 -05:00
Jarrod Johnson 825cacde0e Fix relay dhcp behavior
The refactor for multiple nics on same vlan omitted
a required parameter.
2025-02-12 09:52:23 -05:00
Jarrod Johnson e87d6652ca Fix type of height when pulled from attributes
location.height was left as string, which fouled
further processing.
2025-02-11 08:35:43 -05:00
Jarrod Johnson 76d4556501 Add a go version of genpasshmac 2025-02-07 10:19:54 -05:00
Jarrod Johnson 543a42edd6 Disable SELinux policy in EL diskless images
The SELinux policies do not currently work in a diskless
build, disable by default, though a user may try to enable
it manually after build.
2025-02-06 16:30:06 -05:00
Jarrod Johnson 82fe75e457 Add aliases to attrib clear
Support aliases when specified in clearing.
2025-02-06 15:59:29 -05:00
Jarrod Johnson 9b59c2fadb Have httpapi support multiple shell sessions 2025-02-06 13:25:39 -05:00
Jarrod Johnson 52497d7d95 Broaden except clause on automation check
For whatever reason, we can't seem to specifically catch
the CalledProcessError and have to resort to generic Exception.
2025-02-06 10:44:59 -05:00
Jarrod Johnson 2fcfbe9774 Fix multi-session access to shell
Shell sessions are now wired up to vtbufferd

The shellserver now correctly accounts for sessions being started.

The sockapi now correctly allows the client to specify/attach
to a specific session id.
2025-02-05 16:57:26 -05:00
Jarrod Johnson 564e136dc5 Always provide a badreadings output, even if empty 2025-02-04 09:11:53 -05:00
Jarrod Johnson b9f4051396 Export variables set in confluent functions 2025-02-03 16:40:57 -05:00
Jarrod Johnson e901559644 Add mechanism to explicitly ignore nics for netboot
A service.cfg configuration can be applied to ignore nics for netboot

# cat /etc/confluent/service.cfg
#[http]
#bindhost = /var/run/confluent/httpapi

[netboot]
ignorenics=enp65s0f1np1,enp65s0f3np3
2025-01-30 15:25:10 -05:00
Jarrod Johnson e536789c9d Mitigate send of duplicate replies
If an unrelated network interface shares a vlan with an otherwise
pertinent interface, defer and be silent to avoid confusion on the line.
2025-01-30 14:27:42 -05:00
Jarrod Johnson 7493cc5d48 Normalize enclosure handling 2025-01-30 09:37:10 -05:00
Jarrod Johnson 0fadb00acf Pass through slot geometry if provided 2025-01-30 08:03:36 -05:00
Jarrod Johnson b89ae4d74a Fix bytes being stored in db on identity image use 2025-01-27 12:58:42 -05:00
Jarrod Johnson 79d5a637a7 Correct syntax error in confignet 2025-01-24 11:12:25 -05:00
Jarrod Johnson 67aaee3b4e Adapt to the bond modes
When the team modes were defined in attributes, it was based on the
teamd names.  Since the ecosystem abandoned teamd, we went back to
bond.

However, we neglected to map all the names to the closest bond type equivalent.

Change confignet to do the mapping.
2025-01-24 07:58:31 -05:00
Jarrod Johnson e3d70f351d Provide internal URL shortening service
Permit users to have very long profile names, and provide
a URL shortening service to bridge the gap for fixed-width
field limitations in DHCP/PXE.
2025-01-22 15:44:49 -05:00
Jarrod Johnson 2f33aa5d83 Merge pull request #174 from tkucherera-lenovo/l2traceroute
l2traceroute
2025-01-22 15:30:14 -05:00
Tinashe d4fbd021ad l2traceroute 2025-01-22 09:49:46 -05:00
Jarrod Johnson 24f0ff5221 Add scripts to adopt a node to confluent SSH 2025-01-21 16:48:42 -05:00
Jarrod Johnson fb8675ddc5 Fix SMM3 discovery by switch 2025-01-21 10:10:40 -05:00
Jarrod Johnson cdfb76de57 Try alternate invocation for handshake
Newer versions of websocket change internal call, and we must follow.

This is a consequence of the library providing no means to customize the
TLS handling, so we have to dig in a little to get that customization.
2025-01-14 08:59:24 -05:00
Jarrod Johnson 32bc5afe03 Generate error on node/group misdeletion
If requesting to delete a group from a node when that node is
not a member of that group, generate an error.

Similarly to delete a node from a group.
2025-01-13 12:07:39 -05:00
Jarrod Johnson e2bb72cc14 Allow Unix socket for http socket
If service.cfg has:
[http]
bindhost = /var/run/confluent/httpapi

Then it will use the cited path to create a unix socket instead
of a network socket.
2025-01-08 15:59:48 -05:00
Jarrod Johnson 0cae0fe06e Add installtodisk support for el9 diskless images 2024-12-13 19:04:15 -05:00
Jarrod Johnson cd2509c485 Ignore unparseable net config files
If some pre-processing has rendered config files
unparseable, ignore the file as we can't intelligently rewrite
those.
2024-12-13 16:16:12 -05:00
Jarrod Johnson 8e0bc43008 Fix for SMMv3 onboarding 2024-12-13 16:15:23 -05:00
Jarrod Johnson ddd97388a6 Implement discovery for newer SMMv3 firmware 2024-12-11 10:22:10 -05:00
Jarrod Johnson 2c9b526de4 Repeat the interface loop for Ubuntu identity deploy
It may happen that the first pass at nics misses
a viable network interface due to slow link up
or slow spanning tree forwarding.

Repeat the loop through the interfaces to have follow
up chances at success.
2024-12-05 14:26:26 -05:00
Jarrod Johnson 5d6a935bec Bump genesis version 2024-12-05 10:21:12 -05:00
Jarrod Johnson 23cb1fa8ab Refresh genesis license handling 2024-12-05 10:18:16 -05:00
Jarrod Johnson 5f90aa4f69 Add SMMv3 handler for SMMv3 discovery 2024-12-03 15:00:10 -05:00
Jarrod Johnson 64895c9f95 Return empty hifurl list when non existent
For systems without a host interface,
properly show an empty list.
2024-12-03 14:55:50 -05:00
Jarrod Johnson 8bdabdc962 SMMv3 discovery support
The SMMv3 doesn't respond to the correct SSDP service, add the
odd service.

 Have SMMv3 use the standard redfish handler.

 Augment the standard redfish handler to deal with non-error
 password change required message.
2024-12-03 14:34:11 -05:00
Jarrod Johnson 3fa6b47995 Do not json dumps a string that is already json 2024-12-02 16:50:13 -05:00
Jarrod Johnson f1f433041c Restore underscore headers
Eventlet has "helpfully" stopped supporting headers with
underscores.  Restore them since we want to support
backwards compatibility and do not have the option to
just ignore existing clients.
2024-11-26 12:09:04 -05:00
Jarrod Johnson ebecc9c844 Merge pull request #170 from tkucherera-lenovo/webauth_update
use webauthn instead of webauthn-rp
2024-11-19 10:38:24 -05:00
Tinashe ff523a0d5c change the server spec file 2024-11-19 10:10:02 -05:00
Tinashe efda4b4ef7 remove LICENCE,VERSION and devel prints 2024-11-19 10:08:56 -05:00
Tinashe 8e89c8f622 use webauthn instead of webauthn-rp 2024-11-19 09:39:29 -05:00
Jarrod Johnson a0ffc11d6f Expand type for GUI usage 2024-11-15 09:24:04 -05:00
Jarrod Johnson 9c589e8352 Regenerate initrd after install
The drivers on target may differ from source, regenerate initramfs to allow for booting
2024-11-15 09:19:51 -05:00
Jarrod Johnson f88e9ecebf Support discovery through second XCC NIC 2024-11-14 08:03:34 -05:00
Jarrod Johnson 2f3a8619e8 Fix vinz VNC for non-root users
Relax permissions a tad to allow users to attempt
to connect if they otherwise know the socket name.
2024-11-12 16:16:47 -05:00
Jarrod Johnson 5df30881f8 Provide resource to check if http has been initialized
This allows clients to know if they need to direct user to do
early setup procedures.
2024-11-11 15:31:12 -05:00
Jarrod Johnson b1f8cf8f12 Avoid redrawing 'powered off' redundantly.
If the power state stays the same between queries, take no action to clear screen and
draw redundant data.

In the case of misreporting devices, it mitigates the impact of incorrect reporting,
while generally preserving the output behavior when accurate.
2024-11-11 13:51:10 -05:00
Jarrod Johnson d8c633a7d5 Add localhost to ssh principals/equiv
It shouldn't be possible to hijack localhost, so
allow such addresses to be principaled and be listed in equiv.
2024-11-11 08:03:57 -05:00
Jarrod Johnson 523d5920bc Add a sample script for grabbing XCC screenshots 2024-11-08 12:10:15 -05:00
Jarrod Johnson 9b6204db4f Switch to the type of the member interface
The 'team-slave/bond-slove' type is unneccesary, and
messes up with infiniband.

NetworkManager gets the idea if the 'ethernet' is a bond member without being told explicitly.
2024-10-28 13:21:54 -04:00
Jarrod Johnson a298ef8d74 Catch OpenBMC disconnects and handle them better 2024-10-28 09:41:38 -04:00
Jarrod Johnson 008c1308b4 Handle nvm subsystem without driver.
A variant of the M.2 RAID enablement kit does not manifest with nvme
driver.  Address this by allowing 'nvm' subsystype. to allow blank driver.

Also, to be on the safe side, have self.driver always be a string,
so it can be 'falsey' but still work as a string.
2024-10-26 08:16:56 -04:00
Jarrod Johnson b46a1e14a3 Fix video console when first run has multiple nodes
If client requested more than one on a fresh confluent run,
then only one of the video consoles would properly wait.

Fix by wrapping the assure in a startingup check.
2024-10-25 12:11:58 -04:00
Jarrod Johnson a46bcfa2b5 Add CentOS Stream 10 and Alma Kitten 10
Similar to 9, but now hooks must be in /var instead of /usr
2024-10-25 09:52:10 -04:00
Jarrod Johnson 773cab8189 Merge pull request #169 from tkucherera-lenovo/Staging
enable ability to clean up assets
2024-10-22 13:41:28 -04:00
tkucherera ab0f48f351 enable ability to clean up assets 2024-10-22 12:05:23 -04:00
Jarrod Johnson b99e4c94a0 Add Enlogic PDU support 2024-10-17 14:56:19 -04:00
Jarrod Johnson 3560415668 Update attribute inheritance on rename 2024-10-16 11:40:00 -04:00
Jarrod Johnson 81b57d5db6 Avoid potential endless recursion
If we are detaching, skip reattach in scenario
that leads to infinite recursion.
2024-10-10 16:22:58 -04:00
Jarrod Johnson b05b36484b Fix file staging in http api 2024-10-10 12:52:28 -04:00
Jarrod Johnson 3a0218c421 Simplify profile label outside of bootloader 2024-10-07 13:51:55 -04:00
Jarrod Johnson 84c119ce3d Reduce mandatory newlines between textgroup output 2024-10-04 09:19:19 -04:00
Jarrod Johnson 910af18a00 Fix http websockify 2024-09-30 13:57:09 -04:00
Jarrod Johnson 3ad53a3aac Fix client file staging
Skip read during httpapi, and inject sleep between file transfer chunks.
2024-09-27 15:30:59 -04:00
Jarrod Johnson 2fa56f4a38 Merge remote-tracking branch 'xcat/master' 2024-09-26 07:56:17 -04:00
Jarrod Johnson 7793de39b4 Merge pull request #165 from Obihoernchen/nodensensors-help
Fix nodesensors --skipnumberless help text
2024-09-26 07:54:24 -04:00
Markus Hilger a3212d7603 Fix nodesensors --skipnumberless help text 2024-09-26 13:19:21 +02:00
Jarrod Johnson ed2a8b6f9d Provide an example to name constrain a CA
It's imperfect, and abetter procedure should be written up
for the more security conscious.
2024-09-23 10:45:31 -04:00
Jarrod Johnson 71a83ac39c Try for more DNS lookups
Try to hit likely DNS names, or at least provide a means
of manipulating /etc/hosts to induce
a good domain for the default certificate SAN fields.

Note putting the FQDN first in /etc/hosts will get the FQDN in the
certificate.
2024-09-20 18:34:02 -04:00
Jarrod Johnson a8df3692b6 Persist passkeys as text
confluentdbutil and collective would choke
on the binary.  Have the binary bits be
safely converted to/from base64.
2024-09-20 17:26:02 -04:00
Jarrod Johnson 65ae52782e Merge pull request #164 from tkucherera-lenovo/webauth_update
remove hardcorded values
2024-09-19 16:29:33 -04:00
tkucherera 936153490a remove hardcorded values 2024-09-19 16:21:39 -04:00
Jarrod Johnson f19234419d Implement non-root ssh for SUSE diskless 2024-09-19 13:15:10 -04:00
Jarrod Johnson 787e8b95c0 Merge pull request #163 from tkucherera-lenovo/webauth_update
fix minor bugs and code clean up
2024-09-18 16:30:58 -04:00
tkucherera 9bce0de93d fix minor bugs and code clean up 2024-09-18 16:22:09 -04:00
Jarrod Johnson dbfb800c1b Fix regression in pyghmi dependency version 2024-09-12 13:26:15 -04:00
Jarrod Johnson 942bbd1c69 Merge pull request #154 from tkucherera-lenovo/webauthn
Webauthn
2024-09-12 13:25:15 -04:00
Jarrod Johnson bd37b1746d Merge pull request #136 from tkucherera-lenovo/firwareUpdateServer
Firware update server
2024-09-12 13:24:29 -04:00
Tinashe Kucherera 5609d4fe4b Merge branch 'master' into firwareUpdateServer 2024-09-12 11:44:22 -04:00
Tinashe Kucherera c2abe7c4cd Merge branch 'master' into webauthn 2024-09-12 11:40:20 -04:00
Jarrod Johnson 78dc6e31d7 Merge pull request #133 from tkucherera-lenovo/staging
Staging
2024-09-12 11:38:49 -04:00
Tinashe Kucherera bbc032056e Merge branch 'master' into firwareUpdateServer 2024-09-12 10:37:34 -04:00
Tinashe Kucherera 304d0b5dce Merge branch 'master' into staging 2024-09-12 10:29:52 -04:00
tkucherera d553ab864b resolve merge conflicts 2024-09-12 10:27:05 -04:00
tkucherera db381d377b account for timeout 2024-09-12 10:10:53 -04:00
Jarrod Johnson 7da3944b2b Allow blink for ipmi
OEM IPMI may now do blink
2024-09-11 09:13:30 -04:00
Jarrod Johnson 8704afcee5 Add glue to confluent api from vinzmanager 2024-09-10 11:28:00 -04:00
Jarrod Johnson 0fb19ce263 Wire up http sessions to vinzmanager 2024-09-06 13:41:50 -04:00
Jarrod Johnson c048439849 Reuse existing vinz unix session for a node 2024-09-05 11:44:29 -04:00
Jarrod Johnson f8715f4cb1 Implement logout on disconnect notification for vinz 2024-09-05 11:42:52 -04:00
Jarrod Johnson d17d5341f1 Imprement basic vinz management 2024-09-04 19:16:41 -04:00
Jarrod Johnson 2c76d94a6d Vary version for debian build process 2024-09-04 12:13:40 -04:00
Jarrod Johnson 7c8f85eb06 Handle python mangling of filename consistently for rpm build 2024-09-04 10:53:05 -04:00
Jarrod Johnson ee067fa3c0 Cleanup stray debian content in apt 2024-09-04 10:27:00 -04:00
Jarrod Johnson 4a2e943f84 Update osdeploy rpms to new version scheme for snapshots 2024-09-04 10:19:11 -04:00
Jarrod Johnson 97e29a5655 Change versioning to consistently produce prerelease consistent with rpm and deb 2024-09-04 10:11:47 -04:00
Jarrod Johnson cb67c83287 iAttempt to be consistent with ~ prerelease versioning
We may not know where we are going, but at least bump the minor number.

Ultimately we may not be building toward that number, or that number will be used in a different branch, but it
can at least handle more cases
2024-09-04 08:11:42 -04:00
Markus Hilger e11c3516e9 Create README.md (#162) 2024-09-03 12:25:15 -04:00
Jarrod Johnson 1f6987bafc Fix nodedeploy -c with profile
Remove vestigial statement near end, and put an up front
clarification to a user trying to use both '-c' and a
profile on the same command line.
2024-08-31 07:28:51 -04:00
Jarrod Johnson f4f5b4d1b6 Suppress bad gateway warning if the client ip is unknown
In a scenario where we are doing the 'next-server' next to a real dhcp server,
but through relay, the missing gateway would be expected.

Rely on the final message about 'no address' as the clue to users
that something went wrong on the node side.
2024-08-29 08:57:39 -04:00
Jarrod Johnson fd301c609f Add additional log data to relaydhcp 2024-08-29 08:51:22 -04:00
Jarrod Johnson 53b9a13a51 Fix different invocations of check_fish
Particularly nodediscover register can fail.

Those invocations are XCC specific, so the targtype should not matter
in those cases.
2024-08-28 19:19:39 -04:00
Jarrod Johnson cd91ed0b94 Fix escape warning on newer python 2024-08-27 15:55:54 -04:00
Jarrod Johnson 4dc54b92d5 Correct nodeconsole syntaxwarning 2024-08-27 11:35:39 -04:00
Jarrod Johnson 08a3a0ee76 Correct wrong pyghmi version in dependencies 2024-08-27 10:43:47 -04:00
Jarrod Johnson b601cd97c7 Bump pyghmi to a higher explicit version 2024-08-27 10:36:30 -04:00
Jarrod Johnson 1d80e2703c Add extended nodeconfig to confluent redfish 2024-08-27 09:59:16 -04:00
Jarrod Johnson 7304c8e3b7 Fix LLA request for deploycfg
If a client uses IPv6 LLA, the '%' location may slip in.
In such a case, disable client ip matching, since fe80::
is useless for that anyway.
2024-08-26 16:51:35 -04:00
Jarrod Johnson d84a76dbc6 Fix -a and -e nodeconfig 2024-08-26 10:01:24 -04:00
Jarrod Johnson 4f1b6b1fac Add extra_advanced to core resource tree. 2024-08-26 09:42:44 -04:00
Jarrod Johnson 77c5b70ad9 Wire up '-a -e' for nodeconfig 2024-08-26 09:34:58 -04:00
Jarrod Johnson c7d87b755a Add logic to get remote deployers locked into current nic 2024-08-23 18:02:15 -04:00
Jarrod Johnson f0c5ac557f Fix and extend Relay DHCP Support
Relay DHCP support needed better logging and behavior.

It had also broken non-relay clients.
2024-08-23 13:54:27 -04:00
Jarrod Johnson 5d4f0662d1 Fix add_local_repositories for routed IPv4
Routed IPv4 deployment is not guaranteed to have
an IPv6 server.  In this case the safer bet is
to try to just accept the IPv4 anyway.
2024-08-23 07:06:37 -04:00
Jarrod Johnson edc3a3e9f3 Have confignet fallback to unicast per deploycfg
In routed deployments, the scan mechanism
will not be available. Fall back to routed
access to the deploy server as indicated
by deploycfg from install time.
2024-08-22 16:39:52 -04:00
Jarrod Johnson 3d53b76317 Fix relay replies being broadcast instead of unicast 2024-08-22 14:54:48 -04:00
Jarrod Johnson 683a160c20 Amend mistake in parameter name 2024-08-22 10:25:15 -04:00
Jarrod Johnson 82be3c91d5 Add support for relay DHCP
Use the relay DHCP agent information as basis for
subnet comparison instead of self, when present.

Use the candidate prefix length verbatim since the
relay will offer no hint as to the 'proper' prefix
length for the target segment.
2024-08-22 10:20:04 -04:00
Jarrod Johnson 9cf199a53e Merge pull request #160 from Obihoernchen/typo
Fix small typo
2024-08-22 08:42:06 -04:00
Markus Hilger e735a12b3a Fix small typo 2024-08-22 12:38:52 +02:00
Jarrod Johnson cbd457b464 Cancel the recvr task on close
This avoids stail recvr from sending duplicate data.
2024-08-21 09:12:18 -04:00
Jarrod Johnson dd2119c6d9 Ignore very old ssh key file 2024-08-19 16:26:48 -04:00
Jarrod Johnson 4640cb194f Provide workaround for XCC refusal to rename the initial account 2024-08-19 13:28:49 -04:00
Jarrod Johnson fb10221e1b Amend affluent error handling
Be more consistent and informative
2024-08-16 11:26:52 -04:00
Jarrod Johnson d82a982857 Have affluent 'power' status actually at least reaching the service 2024-08-16 10:52:00 -04:00
Jarrod Johnson e6f6919ef4 Merge pull request #96 from weragrzeda/master
i reverted NTP and Eaton, Only Geist PDUs merging
2024-08-16 09:33:01 -04:00
Jarrod Johnson 1a40842f06 Fix osdeploy updateboot to find multiple grub.cfg 2024-08-15 10:54:52 -04:00
Jarrod Johnson 82e0d9c434 Rework ssh key init to reset key and use context management 2024-08-14 16:08:02 -04:00
Jarrod Johnson 83a4df49c7 Merge pull request #159 from adrianreber/2024-08-13-cat-keys
Do not overwrite the node SSH key with the last found public key
2024-08-14 16:04:36 -04:00
Jarrod Johnson c442c8704d Merge remote-tracking branch 'xcat/master' 2024-08-14 11:41:09 -04:00
Jarrod Johnson 28b88bdb12 Add reporting of skipped nodes in a 'skip' merge 2024-08-14 11:40:11 -04:00
Jarrod Johnson 29d0e90487 Implement confluentdbutil 'merge'
For now, implement 'skip', where conflicting nodes/groups are
ignored in new input.
2024-08-14 11:26:51 -04:00
Adrian Reber a6a1907611 Do not overwrite the node SSH key with the last found public key
Instead of overwriting the SSH public code for the node concatenate all
found SSH keys together in one file.

Signed-off-by: Adrian Reber <areber@redhat.com>
2024-08-13 17:30:43 +02:00
Jarrod Johnson ba7a0f7eab Merge pull request #158 from Obihoernchen/vlan
Add VLAN/PKEY support to confignet (fix #157)
2024-08-13 11:10:19 -04:00
Markus Hilger 0961174425 Remove redundant code 2024-08-09 19:55:42 +02:00
Markus Hilger 005adec437 Add error handling for interface_names 2024-08-09 19:45:19 +02:00
Markus Hilger 6943c2dc0f Make sure VLAN/PKEY connections are created last
Needed for VLANs on bond connections etc.
2024-08-09 19:38:45 +02:00
Markus Hilger 6833cd9c53 Add VLAN/PKEY support to confignet
Introduce new node attribute net.vlan_id to support VLAN/PKEY
configuration using confignet.
2024-08-09 17:59:34 +02:00
Jarrod Johnson 8fd39c36bb Fix some mistakes in confignet 2024-08-09 07:55:42 -04:00
Jarrod Johnson 2fc4483bba Backport SLP performance enhancement from async branch
Same concept that could bog down async variant
could be a slowdown for normal confluent.
2024-08-08 17:09:33 -04:00
Jarrod Johnson 4453ba3b64 Add cpio to confluent_server
In order to do osdeploy processing, we must have cpio
2024-08-07 09:20:34 -04:00
Jarrod Johnson ca4955101d Improve "realness" of imgutil exec context
Utilities that expected /dev/pts will now be satisfied,
as a new /dev/pts is mounted.

Further, systemd added a check in various utilities that
was fouled by the previous method of appearing to have a
root filesystem.

Before, after chroot, we would bind mount / to itself, and this
made things using /proc/mounts, /proc/self/mountinfo, df, mount,
etc happy that there is a real looking root filesystem.

However, by doing it after the chroot, systemd could statx on '..' and
get a different mnt id than /. So it had to be done prior to the
chroot.  However it also had to be done before other mounts as
bind mounting over it would block the submounts.

This more closely imitates the initramfs behavior, where '/' starts life
as a 'real' filesystem before being mounted up and switched into.

This behavior was made to imitate the 'start_root.c' behavior as that
seems to be more broadly successful.
2024-08-07 08:40:10 -04:00
Jarrod Johnson 187fda4bb8 Add debootstrap dependency for imgutil 2024-08-07 07:58:08 -04:00
Jarrod Johnson 7ab7600492 Add cpio dependency for imgutil 2024-08-07 07:56:11 -04:00
Jarrod Johnson f2b9a4fa5d Improve handling of ssh service being pre-hooked 2024-08-06 12:25:21 -04:00
Jarrod Johnson ef1f51ef98 Wire in bmc config clear to redfish 2024-08-06 10:05:39 -04:00
Jarrod Johnson 21b1ac7690 Remove asyncore for jammy
asyncore isn't needed before noble
2024-08-06 09:34:46 -04:00
Jarrod Johnson feaef79060 Successfully track credential currency across change 2024-08-06 09:30:13 -04:00
Jarrod Johnson 8c13816331 Fix fetch of model name for XCC3 systems 2024-08-05 15:03:00 -04:00
Jarrod Johnson e07e6ed152 Improve error handling in OpenBMC console 2024-08-05 14:56:23 -04:00
Jarrod Johnson 0afc3eb03a Port SSDP improvements to SLP
It may not apply, but better to be consistent.
2024-08-05 13:12:54 -04:00
Jarrod Johnson 0fd07e8427 Fix race condition in SSDP snoop
If an asynchronous handler is slow to
enroll a target while another target causes an iteration
of the snoop loop, the various modified structures
had been discarded in the interim.

Now persist the data structures iteration to iteration,
using 'clear()' to empty them rather than getting
brand new data structures each loop.
2024-08-05 13:09:50 -04:00
Jarrod Johnson fc5c1aa90f Fix SSDP error during merge 2024-08-05 11:32:57 -04:00
Jarrod Johnson 30c4d6b863 Add IPMI enablement to generic Redfish handler
If attributes indicate desire for IPMI, try to accomodate.
2024-08-05 11:07:50 -04:00
Jarrod Johnson cfb31a0d8d Implement XCC3 discovery
For XCC3, change to generic redfish onboarding mechanism.

Extend the generic mechanism to be more specific in some
ways that the XCC3 is pickier about. However, it's just reiteration
of what should have already have been the case.
2024-08-05 10:00:22 -04:00
Jarrod Johnson e9d4174ce5 Reapply "Add MegaRAC discovery support for recent MegaRAC"
This reverts commit 9d979256eb.
2024-08-05 08:35:10 -04:00
Jarrod Johnson ed33b4e93f Merge branch 'megaracdisco' into v4xcc 2024-08-05 08:31:47 -04:00
Jarrod Johnson 4b6d41d2f8 Begin work to support V4 Lenovo servers
V4 Lenovo servers will have XCC3, and will have differences
and mark an unambiguously redfish capable onboarding process.

For now identify XCC3 variants and mark them, stubbing them
to the xcc handler.

An XCC3 handler will be made basing on the generic redfishbmc handler
with accomodations for XCC specific data (e.g. DeviceDescription
attributes and the Lenovo default user/password choice).
2024-08-02 17:35:39 -04:00
Jarrod Johnson acce4de739 Add support for an OpenBMC modification
While stock OpenBmc does not care about subprotocols,
some implementations use it as a carrier for the XSRF-TOKEN.

Since base OpenBmc ignores it, we just offer it to any implementation
just in case.
2024-08-02 11:57:04 -04:00
Jarrod Johnson 89bd7c6053 Force load IB/OPA modules in case of IB boot
Ubuntu diskless was not working with boot over IB
2024-08-01 09:40:39 -04:00
Jarrod Johnson 71ca9ef76c Fix path to ntp servers in user-data mod for ubuntu 2024-07-29 15:57:34 -04:00
Jarrod Johnson 1c4f1ae817 Try to add ntp and timezones to Ubuntu scripted install 2024-07-29 15:21:10 -04:00
Jarrod Johnson e6dc383d25 Fix mistake in EL8/EL9 LUKS 2024-07-29 11:22:07 -04:00
Jarrod Johnson 329f2b4485 Amend cryptboot implementation for Ubuntu 22/24, EL8/EL9
Provide mechanism for administrator to place a custom
key for potential interactive recovery into
/var/lib/confluent/private/os/<profile>/pending/luks.key

If not provided, generate a unique one for each install.

Either way, persist the key in /etc/confluent/luks.key, to
facilitate later resealing if the user wants (clevis nor systemd
prior to 256 supports unlock via TPM2, so keyfile is required
for now).

Migrating to otherwise escrowed passphrases and/or sealing to
specific TPMs will be left to operators and/or third parties.
2024-07-29 10:17:14 -04:00
Jarrod Johnson bee9f18197 Tolerate / in the apikey for LUKS setup
The apikey is highly likely to have a /, and so we need to use something
not in the base64 alphabet as a delimiter.
2024-07-26 17:59:42 -04:00
Jarrod Johnson 1af898dcb8 Fix encryptboot on EL8/EL9 2024-07-26 17:43:51 -04:00
Jarrod Johnson 332068074d Extend systemdecrypt hook to support Ubuntu 24.04
Ubuntu 240.4 systemd-cryptsetup now has an external dependency.
2024-07-26 16:54:58 -04:00
Jarrod Johnson 2df902e80e Remove luks password from argv
Pass the luks password by environment variable instead.
2024-07-26 14:07:54 -04:00
Jarrod Johnson 7a602f58b2 Fixes for ubuntu profile tpm support 2024-07-26 13:47:13 -04:00
Jarrod Johnson c563f48c71 Fix assignment of lukspass variable. 2024-07-26 12:30:41 -04:00
Jarrod Johnson c1747ad24c Correct spelling of key for luks check 2024-07-26 11:54:10 -04:00
Jarrod Johnson 1ddf735590 Fix omitted argument to addcrypt 2024-07-26 11:50:53 -04:00
Jarrod Johnson f482d2ead9 Amend crypt hook check
The comment was changed, check for password instead.
2024-07-26 11:35:49 -04:00
Jarrod Johnson 58ee85f39e Rework Ubuntu addcrypt support
The comment based hook is destroyed during early install process.

Use python to manipulate the autoinstall file in a more sophisticated way.

Also refactor the initramfs hook material to be standalone files.
2024-07-26 11:33:01 -04:00
Jarrod Johnson 1d6009a2f2 Switch to using systemd-cryptenroll
The design more cleanly uses luks slot, but
requires providing initramfs hooks.

Those hooks are provided now.
2024-07-26 10:33:38 -04:00
Jarrod Johnson 6d15633a95 Merge branch 'master' into ubuntucryptboot 2024-07-25 15:57:00 -04:00
Jarrod Johnson dc7c9f4a3d Have SSDP fallback to unverified noderanges when looking at candidates 2024-07-25 15:26:23 -04:00
Jarrod Johnson 956e473fa6 Have SSDP fallback to unverified noderanges when looking at candidates 2024-07-25 15:25:09 -04:00
Jarrod Johnson 626f16cb6f Ignore duplicate specifications of same key
Particularly if traversing a lot of linked configuration, the same key/cert
path may come up multiple times, check for equality
and if equal, just keep going.
2024-07-25 14:55:06 -04:00
Jarrod Johnson 30aa6f382c Ignore duplicate specifications of same key
Particularly if traversing a lot of linked configuration, the same key/cert
path may come up multiple times, check for equality
and if equal, just keep going.
2024-07-25 14:54:15 -04:00
Jarrod Johnson fe6d44a4bb Merge pull request #153 from Obihoernchen/json-dump-sort
Use natural sort for lists in json dumps
2024-07-25 14:15:15 -04:00
tkucherera fa940579f1 adding webathn-rp dependency 2024-07-25 14:07:27 -04:00
Jarrod Johnson 298be3b30a Point to the C context object rather than python class
The OpenSSL variant of Context is a python class, but it does have
a C context in it.
2024-07-25 14:05:59 -04:00
Jarrod Johnson 80296b6cbc Point to the C context object rather than python class
The OpenSSL variant of Context is a python class, but it does have
a C context in it.
2024-07-25 14:05:10 -04:00
Markus Hilger 41b722c3f7 Use natural sort for lists in json dumps
Previously, items were randomly arranged in lists in the json dump. This meant that the JSON files were different after each export.
Now they are naturally sorted and identical.
This should make it easier to save and compare the JSON dumps in version control systems.
2024-07-25 18:38:23 +02:00
Jarrod Johnson 0f955cd068 Begin work on a cryptboot support for ubuntu
Start implementing a tpm2-initramfs-tool based approach.

This requires a bit of an odd transition as the PCR 7 is likely
to change between the install phase and the boot phase, so
we have to select different PCRs, but that requires
an argument to pass that crypttab does not support.
2024-07-25 11:24:41 -04:00
Jarrod Johnson c3e918fc5f Fix mistake in untethered support 2024-07-25 09:42:24 -04:00
Jarrod Johnson 8f1a1130a8 Add a selfcheck to check misdone collective manager 2024-07-24 15:55:04 -04:00
Jarrod Johnson 6e8d8dabd1 Fix whitespace issue 2024-07-24 15:28:03 -04:00
Jarrod Johnson a92edc7924 Apply ownership sanity check even for root
User could accidently run 'confluent' in a way that makes no sense,
block it the most accessible way.

The pid file should have blocked it, but systemd purges the directory
even on failure.
2024-07-24 15:20:02 -04:00
Jarrod Johnson 714fefe31b Fix unethered boot for ubuntu 2024-07-24 14:41:39 -04:00
Jarrod Johnson c91af840e5 Robust handling of relative link resolv.conf
resolv.conf may be a relative link, normal file, or absolute link.

Handle all cases.
2024-07-24 11:12:31 -04:00
Jarrod Johnson 2235faa76d Stop using private interface of PyCA
PyCA changes their minds about which bindings to include.

So make the binding ourselves since PyCA removed it in certain versions.

This is a backport of the implementation from the async port effort.
2024-07-24 08:33:20 -04:00
Jarrod Johnson 8f58567a70 Add ssh to default services of a built ubuntu image 2024-07-23 11:05:51 -04:00
Jarrod Johnson cf4475cfcc Escape the '\W' to avoid stepping on python processing 2024-07-23 10:23:05 -04:00
Jarrod Johnson a94b9235e8 Tighten umask on confignet to avoid ubuntu warnings 2024-07-23 10:14:32 -04:00
Jarrod Johnson bb04faed04 Explicitly request bash under ubuntu, which tends to use dash 2024-07-23 10:01:53 -04:00
Jarrod Johnson 33ed1a5e64 Add onboot for ubuntu diskless 2024-07-23 09:32:20 -04:00
Jarrod Johnson 1ade704daa Fix imgutil copy of ubuntu sources 2024-07-22 16:40:44 -04:00
Jarrod Johnson 34b03da494 Update for Ubuntu 24.04 diskless 2024-07-22 16:33:07 -04:00
Jarrod Johnson 4f18294d93 Fix path in debian build for imgutil 2024-07-22 13:57:38 -04:00
Jarrod Johnson 7154a1d60c Add control file for deb build of imgutil 2024-07-22 13:47:36 -04:00
Jarrod Johnson 69fa3f10c0 Add deb packaging of imgutil 2024-07-22 13:47:29 -04:00
Jarrod Johnson 36ca68f44d Add control file for deb build of imgutil 2024-07-22 13:46:45 -04:00
Jarrod Johnson ede941c0d9 Add deb packaging of imgutil 2024-07-22 13:46:27 -04:00
Jarrod Johnson 294ef8e88c Fix for IB diskless boot to install clone
The infiniband section must be defined for the OS
to use the IB link. If it is missing then networking
does not come up during firstboot.

Fix this by having an inifiniband section including explicitly
declaring use of datagram mode. This should suffice for all
install use cases, and may be changed after firstboot starts.
2024-07-19 09:28:29 -04:00
Jarrod Johnson b61e5fb1ff Merge pull request #151 from Obihoernchen/el-stateful-fix
Fix EL stateful install
2024-07-18 13:06:12 -04:00
Markus Hilger b4a33b8102 Fix EL stateful install
Sometimes stateful install can fail if vgchange -a n is run after dd.
Use wipefs instead and fix order of both commands.
Furthermore, use the $INSALLDISK variable.
2024-07-18 17:35:39 +02:00
Jarrod Johnson 9d5432f8cd Fix network configuration when middle name ends in 'net' 2024-07-18 08:40:40 -04:00
Jarrod Johnson abf12f2b96 Reinstate linuxefi/initrdefi for older GRUB
Technically, Grub never had 'linuxefi/initrdefi' commands
officially, so this is a bit weird.

However, if we see signs of GRUB older than 2.03, we will assume
that is requires the linuxefi/initrdefi commands from
the out of tree patch to support EFI the old way.

This corresponds with EL7.  Other variants seem ok with
the more proper linux/initrd command names.
2024-07-15 11:26:58 -04:00
Jarrod Johnson 5d08919769 Merge pull request #150 from tkucherera-lenovo/nodebmcpasswordUpdate
better error handling
2024-07-15 09:30:22 -04:00
tkucherera 8d726bced9 better error handling 2024-07-15 09:22:59 -04:00
Jarrod Johnson 945dff09f3 Change to generic linux/inird command in Grub
Modern grub has removed these variants, and should only be required for very old non-EFI stub kernels
2024-07-15 08:19:13 -04:00
Jarrod Johnson 7a3e1dfde3 Fix grub fallback path for more grub 2024-07-12 16:48:46 -04:00
Jarrod Johnson c0cc673c63 Make directory exist before creating file 2024-07-12 16:31:06 -04:00
Jarrod Johnson 3aea1ec7d6 Fix list syntax in grub cfg 2024-07-12 16:21:36 -04:00
Jarrod Johnson 08a5bffa90 Write multiple grub.cfg paths
Some have different requirements on how to find grub.cfg
2024-07-12 15:52:49 -04:00
Jarrod Johnson 8c193fe33f Fix issues with firstboot on Ubuntu 22+ 2024-07-12 15:30:47 -04:00
Jarrod Johnson bc624d9360 Fix Ubuntu 24.04 network bring up
Ubuntu 24.04 does not check conf files in /run before assuming dhcp anymore.

Influence its logic to skip dhcp if we have static for it
2024-07-12 15:15:56 -04:00
Jarrod Johnson 7bd41af2cc More properly error on bad requests
Avoid incurring an error code 500 issue in reaction to certain
bad request data.
2024-07-09 08:41:34 -04:00
Jarrod Johnson 4f21e62705 Fix typo in the auth code 2024-07-08 10:02:03 -04:00
Jarrod Johnson dde6ceadfb Allow local ISO to proceed if detected with Ubuntu 2024-07-03 14:36:54 -04:00
Jarrod Johnson 9d979256eb Revert "Add MegaRAC discovery support for recent MegaRAC"
This reverts commit 07005d83ca.

Premature addition to master branch
2024-06-27 11:36:41 -04:00
Jarrod Johnson 8ec836f492 Merge branch 'master' into megaracdisco 2024-06-27 11:36:08 -04:00
Jarrod Johnson 07005d83ca Add MegaRAC discovery support for recent MegaRAC
Create a generic redfish discovery and a MegaRAC specific
variant.

This should open the door for more generic common base redfish discovery
for vaguely compatible implementations.  For now, MegaRAC only
overrides the default username and password (which is undefined
in the redfish spec).

Also, have SSDP recognize the variant, and tolerate odd nonsense
like SSDP replies coming from all manner of odd port numbers (no
way to make a sane firewall rule to capture that odd behavior,
but at application level we have a chance).
2024-06-27 11:25:33 -04:00
Jarrod Johnson 411b2fae49 Merge remote-tracking branch 'lenovo/master' 2024-06-25 16:26:55 -04:00
Jarrod Johnson 762a8ee73f Correct proxyDHCP buffer use
It was possible for proxyDHCP to look past the network designated end of packet.
Fix this by consistently using the memoryview that was trimmed to size.
2024-06-25 16:25:19 -04:00
tkucherera c678510b02 working webauthn backend 2024-06-25 14:37:10 -04:00
Jarrod Johnson f2d9c3868b Draft work on MegaRAC out of band discovery 2024-06-24 15:56:26 -04:00
Jarrod Johnson 9715247cc6 Merge pull request #97 from sjtstg/dev-enos-plugin
Add ENOS management plugin
2024-06-21 13:07:00 -04:00
Simon Thompson 166e4599b9 add enos management plugin 2024-06-21 18:35:10 +02:00
Simon Thompson d231326dfb add class to run cmd by ssh 2024-06-21 18:34:47 +02:00
Jarrod Johnson 162e4d1d1e Add retry logic for the el8 identity image support
This allows slow linking interfaces to come up rather than being missed
2024-06-15 15:43:13 -04:00
Jarrod Johnson 8e407cb96e Correct mistake with confluent uuid copy-in in copernicus 2024-06-14 11:21:46 -04:00
Jarrod Johnson d06be55568 Add dependencies for Ubuntu Noble 2024-06-11 15:51:02 -04:00
Jarrod Johnson 8db6382629 Change autoversion scheme for dev builds
We need to be compliant with python versioning for the
tools to keep working
2024-06-11 09:25:57 -04:00
Jarrod Johnson 663b320868 Add more bounds checking in copernicus 2024-06-07 12:43:15 -04:00
Jarrod Johnson 517242df47 Avoid double run of driver disk content 2024-06-07 11:36:39 -04:00
Jarrod Johnson c6adf8175a Try processing driver disks before udevadm invocation 2024-06-07 11:03:00 -04:00
Jarrod Johnson 38a95131f9 Add more error handling in vtbufferd 2024-06-07 09:36:18 -04:00
Jarrod Johnson 5d416cb1b1 Remove disused dependency list 2024-06-06 11:23:28 -04:00
Jarrod Johnson 451e3ba224 Add nodeapply man page 2024-06-06 09:02:45 -04:00
Jarrod Johnson 6564f8de72 Update license material 2024-06-05 08:39:37 -04:00
Jarrod Johnson bb414524ad Add fallback if timedatectl can't run. 2024-05-30 08:14:58 -04:00
Jarrod Johnson bab0a77cb6 Refresh to CentOS stream 9 2024-05-23 15:15:37 -04:00
Jarrod Johnson 010c8a0a23 Amend EL network bringup
One issue is that there are multiple networkmanager connections,
clean this up, though this seems not to be a functional issue.

However, sometimes the lldpad usage screws up network configuration,
disable the facility by forcibly disabling fcoe sincec that is what triggers lldpad.
wq
2024-05-22 15:45:24 -04:00
Jarrod Johnson c0bcc3791d Fix handling some eatonpdu return values 2024-05-15 12:30:36 -04:00
Jarrod Johnson 172c57c6f1 Fix media location search for EL8
EL8 distributions marked the 'OS' as dracut, workaround by trying to use PRETTY_NAME
2024-05-15 12:29:32 -04:00
Jarrod Johnson 91dce25a8b Merge pull request #149 from tkucherera-lenovo/updateAttrib
check update args before setting anything
2024-05-09 08:52:22 -04:00
Jarrod Johnson 62be16442c Fix passive detection of SLP devices (e.g. SMM)
A mistake in the python3 port caused passive SLP
detection to break. Remedy that mistake.
2024-05-08 11:51:00 -04:00
Jarrod Johnson d0e73c887b Load firewall before esxi installation begins
Parts of esxi install depend on firewall running.  When
we are done with 'odd' networking, restore firewall
to meet that expectation.
2024-05-07 10:06:57 -04:00
Jarrod Johnson b7a5101a34 Provide extra warning about redoing SSH materials 2024-05-03 10:27:01 -04:00
tkucherera 930ff3e20d fix error message 2024-05-02 10:41:30 -04:00
tkucherera 39fb229ef1 check update args before setting anything 2024-05-02 10:29:20 -04:00
Jarrod Johnson 60f8f964f5 Merge pull request #144 from tkucherera-lenovo/nodebmcpassword
nodebmcpassword
2024-04-29 10:50:09 -04:00
tkucherera 8f01f22bb5 add password prompting and env var 2024-04-24 10:00:49 -04:00
Wera Grzeda d779f015d6 sed to use single quotes 2024-04-23 18:14:48 +02:00
Wera Grzeda bf004fb7b9 cleaned geist.py 2024-04-23 15:53:35 +02:00
Wera Grzeda 21b8534fef Revert "my changes to Eaton PDU sensors"
This reverts commit 6d87d11f5e.
2024-04-23 15:29:35 +02:00
Wera Grzeda 3b69c54203 Revert "new eaton pdu power readings"
This reverts commit ac68f1f22c.
2024-04-23 15:08:36 +02:00
Wera Grzeda 9954b227a9 Revert "nodeconfig ntp servers for smms"
This reverts commit 44405baaf3.
2024-04-23 15:06:28 +02:00
weragrzeda c0891faaeb Merge branch 'lenovo:master' into master 2024-04-23 14:59:57 +02:00
Jarrod Johnson 86e612b4bf Move anaconda netroot to not be specified in media sourced
When sourcing from media, do not trigger anaconda netroot
behavior.
2024-04-22 12:47:52 -04:00
Jarrod Johnson 6f2be355ef Source from "local" media if present
Some environments may want to load the bulk of the
media via USB rather than over the network. This prefers
that source if that scheme is detected.
2024-04-22 11:32:27 -04:00
Jarrod Johnson b606882327 Have collate preserve relative whitespace
The change to tolerate either a space or no space ended up
greedily consuming whitespace.  Do best possible in two cases:

For log, use the first line as a clue, and consistently pad or not pad
according to first line.  It won't catch different pad strategies, or
handle first line being indented but other lines not being indented.

For the textgroup variant, allow subsequent lines to revise the
pad downward, and accept any whitespace, not just space.
2024-04-19 08:22:32 -04:00
Jarrod Johnson 10f0fabb8c Fix nodegroup retrieval
nodegroup information was broken by clear warning support.
2024-04-17 15:18:45 -04:00
Jarrod Johnson 0d3e2cee6c Merge pull request #146 from tkucherera-lenovo/sample-postscrits
sample post scripts directory
2024-04-16 09:14:56 -04:00
tkucherera 3b55f500ce sample post scripts directory 2024-04-16 03:16:15 -04:00
Jarrod Johnson 3ba3394a54 Fix None return by exec_on_leader with warnings 2024-04-12 17:32:13 -04:00
Jarrod Johnson a6a2f2f2de Fixes for attribute clear warning behavior
Correct collective behavior for failing to clear on followers.

Also, connect the warnings from the leader to the member issuing the
RPC.
2024-04-12 11:46:17 -04:00
Jarrod Johnson 8e5ee6c9d8 Make orphaned sync runner retire on new sync request 2024-04-10 13:54:06 -04:00
Jarrod Johnson ceaf641c1a Keep reap loop going on error 2024-04-09 16:18:24 -04:00
Jarrod Johnson 01722c18c4 Fix location of idle sleep in syncfiles cleaner 2024-04-09 15:40:40 -04:00
Jarrod Johnson 8fb889ba73 Correct syntax error 2024-04-09 15:27:20 -04:00
Jarrod Johnson eaffb342b2 Reap stale sync runners after a minute dead
If the client never claims the result, delete the sync task.
2024-04-09 15:19:38 -04:00
Jarrod Johnson 1da27083cc Another cleanup of syncfileclient output 2024-04-09 15:08:56 -04:00
Jarrod Johnson 67b3c48dc9 Clean up error output on syncfileclient execution 2024-04-09 14:58:38 -04:00
Jarrod Johnson 8ca9a44476 Provide more interesting response body to syncfileclient 2024-04-09 14:27:00 -04:00
Jarrod Johnson 02f301b5d0 Fix mistakes in syncfileclient change 2024-04-09 13:41:27 -04:00
Jarrod Johnson 33271451d7 Support SHA384 if used as fingerprint 2024-04-09 13:17:19 -04:00
Jarrod Johnson f68f9f4693 Make syncfile step robust or pause
If syncfiles fails, keep it retrying.

Also, slow down sync checking to avoid hammering the system.

Further, randomized delay to spread highly synchronized requestors.

Block attempts to do multiple concurrent syncfile runs.
2024-04-09 11:07:11 -04:00
Jarrod Johnson a4e152c17d Defer disarm until after successful client notification
It is theoretically possible for a client to get disconnected
right in the middle. In such a scenario, err on the side of letting
the mechanism stay armed for the sake of a retry being possible.
2024-04-09 10:31:46 -04:00
tkucherera 272c456435 nodebmcpassword man page 2024-04-03 18:50:46 -04:00
tkucherera 894290f577 nodebmcpassword 2024-04-03 18:46:37 -04:00
Jarrod Johnson 34804b2d5f Provide components for cert management with modern XCC
Refresh getcsr and installcert to handle latest firmware.

Also add ability to have pre-existing CSR, and trust the SAN on the way through.

If this becomes more properly a feature, then would likely impose a SAN
on certs, similar to the SSH principals, rather than deferring to the CSR
to get it right.
2024-04-01 12:13:21 -04:00
Jarrod Johnson 77bb03e96c Merge tag '3.9.3'
Numerous bugfixes
2024-03-29 16:24:48 -04:00
Jarrod Johnson 12bb5d583a Correct the equality message in better messagesw 2024-03-27 08:40:01 -04:00
Jarrod Johnson 03bdbfc8ed Provide more useful error messages on mistakes within [] 2024-03-27 08:39:48 -04:00
Jarrod Johnson 661b2ae815 Filter out nvme 'c' devnames, that are used to refer to paths to nvme
Some versions start manifesting nvme devnames with 'c', which
are to be used to interact with multipath to have raw devices
backing a traditional nvme device.
2024-03-27 08:38:36 -04:00
Jarrod Johnson ddb8c4cce4 Fix a few noderange abbreviations
Also, add some test cases on abbreviation
to help sanity check things in the future.
2024-03-27 08:37:51 -04:00
Jarrod Johnson 17fff4997b Fix omission of info dir in plugins 2024-03-27 08:36:54 -04:00
Jarrod Johnson 7b3129a1a2 Fix FFDC preflight checks
The code was comparing two string constants, instead of
a variable to a constant.  Correct the problem to enable
the preflight checks to work as intended.
2024-03-27 08:36:11 -04:00
Jarrod Johnson d183a3f99c Fix problem where one multicast/broadcast attempt could tank other interfaces
Carrying over change from ssdp, ignore failures on transmit, particularly if
firewall
2024-03-27 08:35:52 -04:00
Jarrod Johnson b3b3627bf9 Remove disused bufferlock
We no longer use a lock on buffer communication, eliminate
the stale variable.
2024-03-27 08:34:36 -04:00
Jarrod Johnson c1afc144cb Change to unix domain for vtbuffer communication
The semaphore arbitrated single channel sharing
was proving to be too slow.  Make the communication
lockless by having dedicated sockets per request.
2024-03-27 08:34:31 -04:00
Jarrod Johnson ac1f7c57b6 Fix lldp when peername is null
Some neighbors result in a null name, handle that.
2024-03-27 08:33:50 -04:00
Jarrod Johnson 19e9c6910d Fix nodeapply redoing a single node multiple times 2024-03-27 08:33:35 -04:00
Jarrod Johnson e38cd5d3e5 Fallback to unverified noderange on candidate manager check in PXE
When doing pxe and the noderange of the candidate managers fails,
try again without validation in case the user omitted collective members
from nodelist, but still used ',' to enumerate them.
2024-03-27 08:31:44 -04:00
Jarrod Johnson f1d3e47439 Logout prior to renaming user
Some firmware cannot tolerate a web session being
active during a rename.  Make sure logout has been done, and
give a retry if needed to let the session close out after
logging out.
2024-03-27 08:31:06 -04:00
Jarrod Johnson f7a2e51f9c fstab fixup for hyphenated lvm vg names 2024-03-26 10:31:29 -04:00
Jarrod Johnson f3d0bd9079 Merge pull request #142 from tkucherera-lenovo/l2traceroute
L2traceroute
2024-03-25 08:06:52 -04:00
tkucherera 296a0e88b4 making the use cases more generic 2024-03-24 11:41:23 -04:00
Jarrod Johnson c60bf68cbc Logout prior to renaming user
Some firmware cannot tolerate a web session being
active during a rename.  Make sure logout has been done, and
give a retry if needed to let the session close out after
logging out.
2024-03-22 12:56:09 -04:00
tkucherera 466ed74961 l2traceroute 2024-03-22 11:37:51 -04:00
tkucherera 838c0920eb l2traceroute 2024-03-22 11:37:12 -04:00
Jarrod Johnson 6ad0e773de Actually have the vformat override return
Performing the super() is hardly helpful if it
doesn't actually copy the return behavior.
2024-03-21 16:28:49 -04:00
Jarrod Johnson 5a7d98c6b8 Enhance error reporting
For one, when using confluent expressions, induce {} to be an error to
trigger an error for someone trying to xargs something.

Another is to add warnings when clear does something deliberately, but
is something that might surprise a user, steering them toward
what they possibly might want to do instead.
2024-03-21 16:09:37 -04:00
Jarrod Johnson 13fc5d9f37 Capture better error data on failed syncfiles
syncfiles can often hang up in unexpected ways,
provide a catch-all.
2024-03-20 09:49:25 -04:00
Jarrod Johnson 559e88b144 Correct vgname for hyphenated node names 2024-03-19 09:41:20 -04:00
Jarrod Johnson 5f801e6683 Correct syntax error in ubuntu arm profile init 2024-03-18 12:45:25 -04:00
Jarrod Johnson 7a6b03097b Fixup Ubuntu 22 ARM support 2024-03-18 12:24:25 -04:00
Jarrod Johnson 6502573d90 Bring ubuntu 22 versions of firstboot and post to 20 2024-03-18 09:15:11 -04:00
Jarrod Johnson 3dd09b95e4 Fix Ubuntu 20 pre script to match 22 2024-03-18 09:13:53 -04:00
Jarrod Johnson a595d31e94 Explicitly invoke bash for ubuntu post
Ubuntu really tries to use non-bash, explicitly use bash when we need it.
2024-03-18 08:56:06 -04:00
Jarrod Johnson b157e55f00 Fallback to unverified noderange on candidate manager check in PXE
When doing pxe and the noderange of the candidate managers fails,
try again without validation in case the user omitted collective members
from nodelist, but still used ',' to enumerate them.
2024-03-15 15:50:58 -04:00
Jarrod Johnson 60fe306890 Numerous fixes
Normalize cloning by wipefs prior to image2disk

Have imgutil filter out zram mounts.

Fix syncfiles error handling.
2024-03-15 13:03:46 -04:00
Jarrod Johnson bd2288ccb7 Ensure preservation of " if rename fails
If ent would swallow a ", make sure to put it back.
2024-03-15 12:29:37 -04:00
Jarrod Johnson 789376029d Numerous fixes to the EL9 cloning
Fix various callbacks when using IPv6 based deployment.

Do not attempt to restore erroneously cloned zram partitions.

Convert LVM names to new LVM names consistent with source naming scheme.

Push new kernel command line into /boot/loader and /etc/kernel/cmdline.
2024-03-15 09:57:23 -04:00
Jarrod Johnson 1d4505ff3c SSH test by IP, to reflect actual usage and catch issues
One issue is modified ssh_known_hosts wildcard customization
failing to cover IP address.
2024-03-14 11:21:41 -04:00
Jarrod Johnson 876b59c1f0 Remove redundant kill on the agent pid
Extraneous kill on the agent pid is removed.
2024-03-14 10:52:52 -04:00
Jarrod Johnson 58d9bc1816 Updates to confluent_selfcheck
Reap ssh-agent to avoid stale agents lying around.

Remove nuisance warnings about virbr0 when present.

Do a full runthrough as the confluent user to ssh to a node when user
requests with '-a', marking known_hosts and automation key issues.
2024-03-14 10:50:26 -04:00
Jarrod Johnson 17af9c74b8 Fix nodeapply redoing a single node multiple times 2024-03-12 15:33:31 -04:00
Jarrod Johnson 0d720baf25 Fix lldp when peername is null
Some neighbors result in a null name, handle that.
2024-03-12 09:37:36 -04:00
Jarrod Johnson 49e614eb32 Have image2disk delay exit on error
Debugging cloning is difficult when system immediately reboots on error.
2024-03-11 17:11:44 -04:00
Jarrod Johnson cdefb400f9 Expose fingerprinting and better error handling to osdeploy
This allows custom name and pre-import checking.
2024-03-11 13:33:15 -04:00
Jarrod Johnson 3ffeef5cf3 Fix stray blank line at end of nodelist
Wrong indentation level for nodelist resulting in
spurious line.
2024-03-06 16:27:09 -05:00
Jarrod Johnson 5ae3f4c62a Properly address runansible error relay 2024-03-06 09:28:24 -05:00
Jarrod Johnson 2f8dfac9bc Dump stderr to client if ansible had an utterly disastrous condition 2024-03-06 09:27:31 -05:00
Jarrod Johnson 75db6da621 Opportunisticlly use sshd_config.d when detected 2024-03-04 08:16:18 -05:00
Jarrod Johnson fa5b1c671e Remove disused bufferlock
We no longer use a lock on buffer communication, eliminate
the stale variable.
2024-02-22 15:07:51 -05:00
Jarrod Johnson 72e26caf36 Change to unix domain for vtbuffer communication
The semaphore arbitrated single channel sharing
was proving to be too slow.  Make the communication
lockless by having dedicated sockets per request.
2024-02-22 15:07:42 -05:00
Jarrod Johnson 21f691cbd8 Correct the equality message in better messagesw 2024-02-13 16:00:50 -05:00
Jarrod Johnson d07e6f86c0 Provide more useful error messages on mistakes within [] 2024-02-13 15:58:08 -05:00
Jarrod Johnson 3a0172cccc Make indirect PDU operations concurrent
Similar to the enclosure reseat work, have indirect
PDU operations be made concurrent across PDUs, though
still serial within a PDU.
2024-02-02 10:35:47 -05:00
Jarrod Johnson 59a31d38a2 Make reseat concurrent
Spawn reseat activity concurrently between chassis.  This should
reduce time to nodes per chassis rather than total nodes.
2024-02-02 08:51:12 -05:00
Jarrod Johnson a17695ad06 Extend confluent PXE support
For relay agent options, preserve and echo back the option,
needed for certain environments.

Also, it turns out that for whatever reason on some platforms, iPXE's
proxyDHCP logic can't seem to get a reply.  In this scenario,
provide the filename in the DHCP offer without waiting for proxyDHCP.

This change may be worth evaluating more broadly, but may carry risk of not working
right with unmanaged DHCP servers.
2024-02-01 16:38:04 -05:00
Jarrod Johnson 7377c44e0f Fix problem where one multicast/broadcast attempt could tank other interfaces
Carrying over change from ssdp, ignore failures on transmit, particularly if
firewall
2024-02-01 08:50:44 -05:00
Jarrod Johnson fc82021f2b Add missing ubuntu24.04 to packaging 2024-01-30 15:04:04 -05:00
Jarrod Johnson 9ad9912ef1 Change to pre-made links for ubuntu24.04 2024-01-30 14:28:11 -05:00
Jarrod Johnson 7618fa8b63 Add diskless links 2024-01-30 14:21:25 -05:00
Jarrod Johnson 170e585e57 Add preliminary ubuntu 24.04 support 2024-01-30 13:53:59 -05:00
Jarrod Johnson 72cace5a50 More thoroughly wire up custom name
Have custom name go through to actual import and influence profile names
2024-01-30 11:11:27 -05:00
Jarrod Johnson d0373977b3 Fix FFDC preflight checks
The code was comparing two string constants, instead of
a variable to a constant.  Correct the problem to enable
the preflight checks to work as intended.
2024-01-30 09:08:28 -05:00
Jarrod Johnson f03525aac5 Merge pull request #141 from tkucherera-lenovo/defaultWebUI
opening web ui using default ip
2024-01-29 16:56:13 -05:00
tkucherera fcb3d917db use socket.getaddrinfo 2024-01-26 17:14:04 -05:00
tkucherera 16ad4e776f opening web ui using default ip 2024-01-26 12:39:25 -05:00
Jarrod Johnson 87454c1ab1 Start browserfs if not yet running 2024-01-26 09:31:59 -05:00
Jarrod Johnson fa3e1202c4 Relax systemd device policy to allow /dev/fuse access 2024-01-26 09:24:41 -05:00
Jarrod Johnson 41675e528f Amend dhcp license path 2024-01-24 15:31:27 -05:00
Jarrod Johnson a3d386dc39 Add NOTICE gathering for some genesis packages 2024-01-24 14:47:23 -05:00
Jarrod Johnson e5051408e5 More license handling 2024-01-23 15:02:08 -05:00
Jarrod Johnson fa7cd2940e More license updates for genesis 2024-01-23 14:39:32 -05:00
Jarrod Johnson e5736ecb51 Update license assets in genesis 2024-01-23 14:18:25 -05:00
Jarrod Johnson b90718982e Implement a number of OS deployment management enhancements.
Add capability to fingerprint media without doing a full import (/deployment/fingerprinting/)

Add fetching the profile info as json under the /deployment/ api.

Prepare to support custom distribution name on import
2024-01-22 17:22:47 -05:00
Jarrod Johnson 07a7357c87 Merge remote-tracking branch 'xcat/master' 2024-01-22 10:40:23 -05:00
Jarrod Johnson dec7454866 Merge branch 'browserfs' 2024-01-22 10:39:35 -05:00
Jarrod Johnson bcc631f88d Set static hostname in diskless boot 2024-01-22 10:39:17 -05:00
Jarrod Johnson 9203ac32e9 Start work on browserfs concept
This will allow WebUI reactivity even with large files for import.
2024-01-17 17:01:49 -05:00
Jarrod Johnson 141760ea19 Merge pull request #140 from henglikuang/boot_order_issue
Fix efivars handling of unexpected unmount
2024-01-17 08:20:17 -05:00
Jarrod Johnson c7628a3638 Merge pull request #139 from henglikuang/master
Add default time zone as UTC
2024-01-17 08:19:55 -05:00
Jarrod Johnson 5fdd6973f1 Update with more license content 2024-01-16 11:11:53 -05:00
Jarrod Johnson 07f91d792a Fix omission of info dir in plugins 2024-01-12 10:52:49 -05:00
Jarrod Johnson 56b644ead9 The 3rd party monotonic is no longer needed 2024-01-11 16:30:45 -05:00
henglikuang1 ea88ccb0ad Fix efivars handling of unexpected unmount 2024-01-11 14:31:45 +08:00
henglikuang1 382feea68d Add default time zone as UTC 2024-01-11 11:44:25 +08:00
Jarrod Johnson 0dfe66f1b2 Fix overzealous reaping of '-lib' folders 2024-01-09 16:08:49 -05:00
Jarrod Johnson cfccb046bc Correct syntax error in draft attempt 2024-01-09 13:36:55 -05:00
Jarrod Johnson 70f91d59b2 Update license material in gathering genesis 2024-01-09 13:32:54 -05:00
Tinashe Kucherera 0016d940e3 Merge branch 'xcat2:master' into firwareUpdateServer 2024-01-04 14:12:51 -05:00
Jarrod Johnson 4d63908164 Have a fallback height of 1 for any missing height 2024-01-04 11:17:02 -05:00
Jarrod Johnson 39c00323b3 Fix error where layout would bail if a partial error were encountered 2024-01-03 15:58:24 -05:00
Jarrod Johnson b0e23121a8 Add stub resize handler
For uninitialized console handlers, provide a stub
to do nothing on resize.

This avoids such a request crashing a shared websocket session.
2024-01-03 15:03:49 -05:00
Jarrod Johnson 85629dea64 Prevent unitiailized collective info
When doing proxyconsole, don't land in a useless retach
loop when managerinfo is None.
2023-12-07 14:45:19 -05:00
Jarrod Johnson 93269a05eb Fix cloning with ipv6 and EL9 2023-12-06 17:06:09 -05:00
Jarrod Johnson 7aef012a42 Correct string join syntax in confignet 2023-12-05 14:39:36 -05:00
Jarrod Johnson 7b89054b35 Fix a few noderange abbreviations
Also, add some test cases on abbreviation
to help sanity check things in the future.
2023-12-01 15:55:39 -05:00
Jarrod Johnson 3e7cdd1caa Merge pull request #138 from mslacken/suseInstall
disable online repos for openSUSE leap
2023-12-01 08:49:42 -05:00
Christian Goll 3aa91b61e5 disable online repos for openSUSE leap
online repositories may not be accesible for the cluster
nodes but were added from the content.xml. Editing this
files with initprofile.sh is impossible as they are executed
in parallel, so all repos starting with
https?://download.opensuse.org
are removed during post

Signed-off-by: Christian Goll <cgoll@suse.com>
2023-12-01 10:57:31 +01:00
Jarrod Johnson 6763c86387 Add DNS to NetworkManager
Similar to netplan, apply DNS to every interface.
2023-11-28 14:35:01 -05:00
Jarrod Johnson 63b737dc52 Correct bonding in confignet for NetworkManager 2023-11-28 14:09:59 -05:00
Jarrod Johnson 55e60d52fd Avoid potential multiple brackets in imageboot.sh 2023-11-28 13:33:21 -05:00
Jarrod Johnson 3730ba049f Fix potential doubling up of IPv6 brackets
There were scenarios where IPv6 URL brackets may double up.
2023-11-28 13:11:25 -05:00
Jarrod Johnson 4fb263e643 Merge pull request #137 from mslacken/python3-dbm
python3-dbm is required for SUSE
2023-11-27 09:53:27 -05:00
Christian Goll 0b28d64c83 python3-dbm is required for SUSE
the python module `anydbm` is part of this python package

Signed-off-by: Christian Goll <cgoll@suse.com>
2023-11-27 15:18:57 +01:00
Jarrod Johnson 68ce3d039d Filter out nvme 'c' devnames, that are used to refer to paths to nvme
Some versions start manifesting nvme devnames with 'c', which
are to be used to interact with multipath to have raw devices
backing a traditional nvme device.
2023-11-27 08:34:34 -05:00
Jarrod Johnson 9757cd1ae3 Check the profile *before* rebooting systems
This provides a much better experience when a typo or
other mistake has a profile that is not actionable.
2023-11-16 10:20:48 -05:00
Jarrod Johnson c9452e65e8 Fix some osdeploy ordering issues
osdeploy initialization dependencies have been
improved and marked if absolutely dependent.
2023-11-15 11:30:20 -05:00
Jarrod Johnson cd07e0e212 Add missing disclaimer from tmt license 2023-11-14 15:14:54 -05:00
Jarrod Johnson f475d58955 Various permission fixes for osdeploy initialize
Fix a few scenarios where certain ordering of
initialize creates unworkable permissions.
2023-11-13 15:43:11 -05:00
Jarrod Johnson ec023831a5 Fix syntax error in confignet 2023-11-09 17:28:38 -05:00
Jarrod Johnson 6e092934e7 Fix for ubuntu clone to nvme 2023-11-09 17:15:17 -05:00
Jarrod Johnson e03f010eac Fix Ubuntu confignet without IPv6
If confignet did not have ipv6 to work with, it
would fail to work at all.

Also handle when the configuration has a blank DNS server in it.
2023-11-09 09:03:59 -05:00
Jarrod Johnson 2cd75ef425 Fix diskless autocons message 2023-11-08 10:22:51 -05:00
Jarrod Johnson e90f2829ab Filter bind mounts from imgutil capture
If bind mounts are in use, it will foul the capture.

Notably, one example is if you install the firefox snap in
ubuntu, snapd creates a bind mount.

This will ignore bind mounts, and rely upon the system to
put it straight.
2023-11-08 09:37:44 -05:00
Jarrod Johnson 8f927d94e9 Switch to bond from team
Teaming is deprecated and EL went back to bond, follow
that guidance.
2023-11-01 11:17:04 -04:00
Jarrod Johnson 8a4ef0b1fe Make link type detection more specific
If the ip command shows altnames, do not
let the altnames interfere with locking
on to linktype.

Further, use show dev instead of grep to be more specific.
2023-11-01 10:42:33 -04:00
Jarrod Johnson 814f420852 Update genesis to deal with CS9 sshd 2023-10-31 11:47:28 -04:00
weragrzeda 80242e35b3 Merge branch 'lenovo:master' into master 2023-10-30 09:03:08 +01:00
Jarrod Johnson a1ac234b73 Enhance error message for authentication issue during syncfiles 2023-10-27 15:31:14 -04:00
Jarrod Johnson d082610678 Add more deep checking of node networking
Whether due to the management node or node IP addresses,
check if deployment can reasonably proceed using IPv4 or IPv6,
and give a warning with some suggestions to check.

Also, add nodeinventory <node> -s as an example resolution for missing
uuid.
2023-10-27 13:34:52 -04:00
Jarrod Johnson 0857716f64 Add support for normalized sensors
This opens the door for normalized common sensors
for clients that care about the semantics but
cannot keep track of inconsistent sensor names from
implementation to implementation.
2023-10-26 08:58:37 -04:00
Jarrod Johnson 49a504972f Fix syntax error in confignet 2023-10-25 14:21:55 -04:00
Wera Grzeda 62ab361ef8 nicer output for inventory 2023-10-23 08:16:27 +02:00
Wera Grzeda ac68f1f22c new eaton pdu power readings 2023-10-20 11:38:11 +02:00
weragrzeda 7972834a62 Merge branch 'lenovo:master' into master 2023-10-20 11:36:38 +02:00
Jarrod Johnson 9c9d71882c Disable keepalive
Unfortunately, apache can get a bit odd over how it
reports a non-viable open socket for keepalive, which
can happen in certain windows.

Disable the keepalive feature and take some performance penalty in
browsers for the sake of more consistent return behavior and
fewer idle greenthreads doing nothing.
2023-10-19 15:51:40 -04:00
Jarrod Johnson 913a26aec9 Change to consistent CWD for osdeploy arm build 2023-10-19 10:42:39 -04:00
Jarrod Johnson 063bfc17a5 Start using container for final build process
Makes supporting the base platform easier by largely ignoring the
base platform.
2023-10-19 10:40:57 -04:00
Jarrod Johnson 8b150a9047 Fix for post group failures
A node failure after group failure would
erase the group from range.

Further, correct an issue where an empty nodeset
would trigger
a bad behavior.
2023-10-19 09:25:57 -04:00
Jarrod Johnson b91a194184 Improve selfselfice performance with yaml
The yaml python default behavior is 'pure python' and is
tortuously slow.

As a test, yaml dump of a 17,000 element list took 70 seconds in default configuration.

Opting into the C functions, that time comes down to 10 seconds, a
nice and easy improvement for generic yaml.

For dumping a simple dumb list (e.g. the nodelist for ssh), a special
case yaml-looking result is done, which hits 0.4 seconds on that same
test. So this special case is added to nodelist, which can be very long
and very in demand at the same time.
2023-10-17 16:29:30 -04:00
Jarrod Johnson 06d18cec63 Fix abbreviation when pad decreases
This is a bizarre way to work, but it should be valid.
2023-10-16 08:29:45 -04:00
Jarrod Johnson 0434f38ea1 Add iterm and kitty image support to stats
This delivers improved graphics
speed and quality for selected terminals.
2023-10-13 15:25:08 -04:00
Jarrod Johnson bfbb7c2843 Handle mid-range pad changing, and identical names with only pad difference
This would be painful to operate, but if done at least
reverse noderange will
faithfully honor it now.
2023-10-12 16:09:40 -04:00
Jarrod Johnson 3a6932ea6d Start tracking padding during abbreviation
This will take care of padding when
padding is consistent across a range.

However, we still have a problem with a progression like:
01
02
...
98
099
100

Where numbers in the middle start getting padding unexpectedly without a leading digit.
2023-10-12 15:28:54 -04:00
Jarrod Johnson 6e4d9d9eb4 Address potential slowdowns by misbehaving DNS
For one, shorten the DNS timeout, if the DNS server is completely out, give up quickly.

For another, if a host has a large number of net.X.hostnames, the sequential nature
was intolerable.
Have each network be evaluated in a greenthread concurrently to serve
the DNS latency concurrently.
2023-10-12 14:46:09 -04:00
Jarrod Johnson 2d906e1886 Fix handling of pre-existing array 2023-10-11 10:15:24 -04:00
Jarrod Johnson e9a2f57ad8 Simplify the noderange abbreviation
Since the multi-iterator ambition is out,
ditch the expensive set wrangling step.

Now the procedure is:
-Suck nodes into groups, as possible
-Separately for groups and nodes:
     -Sort the elements
     -Chunk the elements based on 'non-numberical' situation matching
     -analyze the iterators to apply [] to shorten the name
     -Multi-iterator will cause a discontinuity, and a new ',' delimited name gets constructed
2023-10-10 16:56:32 -04:00
Jarrod Johnson c254564f02 Fully give up on multi-iterator abbreviation
There's too many cases that can go wrong.

Note that with this lower ambition, it would be possible to
significantly streamline the implementation.

Notably, the 'find discontinuities' approach
was selected to *try* to
support multiple iterators,
but since that didn't pan out,
a more straightforward
numerical strategy can
be used from the onset.
2023-10-10 12:47:19 -04:00
Jarrod Johnson fe27cdea4a Abbreviate harder, using brackets
Add a round that collapses as is
convenient to bracketed range.
2023-10-09 17:18:44 -04:00
Jarrod Johnson a4ea5e5c4b Abbreviate sequential nodes
When we have sequential nodes, collapse to ':' delimited range.
2023-10-07 09:51:32 -04:00
tkucherera b3f32eb805 "firmware update on the server side" 2023-10-06 08:32:47 -04:00
Jarrod Johnson 06ee48f702 Merge pull request #135 from tkucherera-lenovo/Nodeattrib
missing_shlex import in nodeattrib
2023-10-05 12:53:16 -04:00
tkucherera 77eec1a791 missing_shlex import in nodeattrib 2023-10-05 11:44:04 -04:00
Jarrod Johnson b60b78327f Merge pull request #134 from tkucherera-lenovo/Nodeattrib
Nodeattrib
2023-10-04 16:32:32 -04:00
tkucherera 2e84c73baa '' 2023-10-04 16:27:05 -04:00
tkucherera 67f607a8f1 fix to synopsis 2023-10-04 16:26:20 -04:00
tkucherera eca1854d56 fix to env doc 2023-10-04 10:37:41 -04:00
tkucherera ba90609f3b documentation for nodeattrib -s 2023-10-04 10:36:58 -04:00
tkucherera c8094276d0 typ0_fix 2023-10-04 10:34:07 -04:00
tkucherera d299db3442 doc 2023-10-04 10:31:24 -04:00
tkucherera 9f168aee73 docs- batch file systax 2023-10-04 10:28:16 -04:00
Jarrod Johnson ee19386d8c Export nodename in ubuntu pre 2023-10-04 09:49:09 -04:00
Jarrod Johnson ef9083062b Make multiple attempts to fetch networking configuration
Since confignet runs early in startup, the networking can be a bit fickle.

Tolerate outages during early use.
2023-10-03 10:13:53 -04:00
Tinashe Kucherera 901f633848 Merge branch 'xcat2:master' into staging 2023-10-02 12:58:14 -04:00
Jarrod Johnson cca0c57e90 Merge pull request #132 from tkucherera-lenovo/nodersync
node rsync -s switch
2023-10-02 12:57:19 -04:00
tkucherera 820d255a1a staging feature 2023-10-02 11:23:23 -04:00
Jarrod Johnson 79e3ad53f8 Add server side rack layout organization
The info is hard to put together client side, but
supremely easy server side.

Provide a nice call to
get the layout for a noderange, similar to (but better than) current
GUI code.

Now GUI can get a nice canned JSON
description of the layout.
2023-09-29 16:23:59 -04:00
tkucherera b63d75f2bb change to remove to many conditionals 2023-09-29 12:07:38 -04:00
tkucherera 378929579f Allow to be able to specify prefix as well 2023-09-28 08:56:52 -04:00
tkucherera eee8bbb498 node rsync -s switch 2023-09-27 17:52:15 -04:00
Jarrod Johnson a00fd325aa Export variables for ubuntu pre.d run 2023-09-27 13:09:23 -04:00
weragrzeda 02d2ce6bfd Merge branch 'lenovo:master' into master 2023-09-21 13:57:12 +02:00
weragrzeda 7b19e67bf0 amperage and outlet fix for geist.py 2023-09-21 06:27:12 +02:00
Jarrod Johnson 3624013889 Merge pull request #130 from tkucherera-lenovo/Nodeattrib
Nodeattrib
2023-09-20 15:07:02 -04:00
tkucherera bd0b16992d man page 2023-09-20 14:42:17 -04:00
tkucherera 4ecbbdfd9a nodeattrib -s use with batch file 2023-09-20 14:37:07 -04:00
tkucherera 5768514ba9 nodeattrib -s attrib.batch 2023-09-20 14:29:21 -04:00
Jarrod Johnson f88b44dee2 Fix issues with imgutil 2023-09-20 10:13:34 -04:00
Jarrod Johnson d0c97b7623 Add pieces of EL profiles 2023-09-19 13:14:07 -04:00
Jarrod Johnson 04505e1bbb Break out partitioning and pagkacelist for EL profiles 2023-09-19 13:01:10 -04:00
Jarrod Johnson d613d0f546 Add openbmc plugin for console 2023-09-18 16:03:48 -04:00
Jarrod Johnson 47fc233cce Fix debian packaging for confluent 2023-09-18 15:48:38 -04:00
Jarrod Johnson 8f80add0f1 Enhance debian packaging for confluent 2023-09-18 15:19:10 -04:00
Jarrod Johnson 0a527f5f39 Add environment to firstboot ubuntu 2023-09-18 11:38:41 -04:00
Jarrod Johnson 3e8c6d1ea6 Correct syntax issue in el7 image2disk 2023-09-18 11:04:50 -04:00
Jarrod Johnson a01b7c6503 Revamp and add missing bits to scripted ubuntu install 2023-09-18 10:30:52 -04:00
Jarrod Johnson 83e3627b47 Add pre.d to ubuntu 22 diskful 2023-09-18 10:19:50 -04:00
Jarrod Johnson 37b75ba777 Correct variable name on commit clear 2023-09-15 15:54:35 -04:00
Jarrod Johnson aa5de3c6a3 Suspend handling of new socket connections while configmanager down 2023-09-15 15:48:37 -04:00
Jarrod Johnson d4c535d038 Halt autonomous discovery handling while configmanager is down
This avoids triggering a potential large amount of churn on transiently
"unknown" systems
that are actually discovered.
2023-09-15 15:32:33 -04:00
Jarrod Johnson 94b8559777 Declare ready on becoming leader
Provide for leader scenario to correctly
flag configmanager as ready.
2023-09-15 15:28:16 -04:00
Jarrod Johnson f2f25fe912 Implement ready tracking
When going through the
dramatic scenario of initializing collective,
take _ready down
so that other code can
pause operation appropriately.
2023-09-15 15:25:26 -04:00
Jarrod Johnson c0629fcce5 Fix invocation of json restore change 2023-09-15 11:41:12 -04:00
Jarrod Johnson 4952e87309 Undo collective manager changes
Abort attempt to avoid duplicate startups, it was incorrect.
2023-09-15 10:52:13 -04:00
Jarrod Johnson 533244458d Do not count as 'initting' until collective starts. 2023-09-15 10:37:51 -04:00
Jarrod Johnson 20f02b5ef7 Avoid searching switches for foreign nodes
Consult collective.manager
to decide to skip
consideration of a node, if
that node shouldn't be managed anyway.

This should avoid "cross-island" behavior for such
environments.
2023-09-15 10:07:14 -04:00
Jarrod Johnson df47c6d0fd Disable attribute notify during json restore
This is guaranteed to be a lot of churn very quickly, disable it for
now.
2023-09-13 17:03:05 -04:00
Jarrod Johnson 97ee8e2372 Cerrect the logic of duplicate discovery protection 2023-09-13 10:50:21 -04:00
Jarrod Johnson 74c6848a0b Avoid redundant setting of known data
Setting attributes can be a touch expensive, since
there's a high risk
of this being old news,
check that discovery hasn't already set values
before trying to set them again.
2023-09-13 09:59:03 -04:00
Jarrod Johnson b75979f3ec Insulate confluent from fatal errors from discovery subscription errors 2023-09-12 16:59:53 -04:00
Jarrod Johnson 50d5cead06 Add prereq checks to EL cloning 2023-09-12 16:55:19 -04:00
Jarrod Johnson e6b0b235e9 Fix image2disk for nvme clone targets 2023-09-12 16:53:32 -04:00
Jarrod Johnson 00eb9e3c9d Fix full_net_config with missing address info 2023-09-12 16:49:15 -04:00
Jarrod Johnson b77d8b1f21 Make yaml import conditional
Only Ubuntu requires it, but tends to have it.

Other distributions do not tend to have it.
2023-09-12 10:45:15 -04:00
Jarrod Johnson d7190c893f Correct networkmanager entries for boot over infiniband
When booting and infiniband comes up as the 'get started' nic,
make the entry use correct type so as to avoid
confusion later, particularly when confignet comes along to fixup
the configuration.
2023-09-11 13:11:17 -04:00
Jarrod Johnson f82829aa0c Add dependency checking to imgutil capture
This will more quickly indicate problems in a profile trying to capture.

First iteration will address Ubuntu.
2023-09-08 17:10:27 -04:00
Jarrod Johnson 203dabfb0b Place nameservers on every NIC in netplan
netplan, like others, makes the questionable choice to designate DNS
as a NIC specific setting, despite not mapping well
to a NIC.

Since we model DNS like NTP, a global, just repeat the DNS config for
every interface.  This redundancy is fine in testing multiple
interfaces.
2023-09-08 16:56:58 -04:00
Jarrod Johnson 9441221150 Have cooltera plugin adapt
As new sensors appear, be more adaptive
to continue tracking existing sensors.
2023-09-08 11:30:57 -04:00
Jarrod Johnson 8de6f4356d Fix sense of new flag
Accidently made flag exactly opposite of intended
2023-09-07 15:12:43 -04:00
Jarrod Johnson fe78034eaa Add '-y' to imgutil build
Allow non-interactive imgutil build.
2023-09-07 14:56:07 -04:00
Jarrod Johnson 691d92f735 Avoid calling implicit nic config if nowhere to put it
If 'None' attributes are in use,
we'd have no where to
stick implicit configuration anyway.
2023-09-07 14:41:16 -04:00
Jarrod Johnson 8ca1f80ef6 Fix implicit nic in confignet
If the implicit IP
is not in any of the
attribute groups of net,
then auto-vivify from the normal place.
2023-09-07 14:36:56 -04:00
Jarrod Johnson 3cacbf283a Fix cloning to NVME boot
The partition device names
have a different scheme
for nvme v. other devices.
2023-09-07 10:09:19 -04:00
weragrzeda 0993ef0c11 Merge branch 'lenovo:master' into master 2023-09-07 13:13:05 +02:00
weragrzeda c950524386 geist.py outlet state fix 2023-09-07 13:08:33 +02:00
Jarrod Johnson 89e573207c Remove irrelevant command from ubuntu cloning firstboot 2023-09-01 16:55:01 -04:00
Jarrod Johnson f16cf4387f Further Ubuntu enhancements
Add confignet to Ubuntu 20 and 22
Add syncfile to the ubuntu diskless/cloning
2023-09-01 16:40:02 -04:00
Jarrod Johnson fa60a9dc9f Add IPv6 support to confignet 2023-09-01 16:34:30 -04:00
Jarrod Johnson 2268d7f65a Fix hotplug firmware in suse diskless 2023-09-01 13:51:17 -04:00
Jarrod Johnson abd5f4e9f2 Fix shebang in firstboot on ubuntu cloning 2023-09-01 13:51:02 -04:00
Jarrod Johnson f6e658c341 Add site CA to ubuntu profiles on install 2023-09-01 13:25:20 -04:00
Jarrod Johnson 44ec390f40 Add post.sh to ubuntu cloning 2023-09-01 12:29:27 -04:00
Jarrod Johnson 6ab91b50af Add missing bits of Ubuntu diskless 2023-09-01 10:55:18 -04:00
Jarrod Johnson 1f32ef2310 Implement basic netplan support
Start with single links, ipv4 only for ubuntu.
2023-09-01 10:07:51 -04:00
Jarrod Johnson 22cb2bdc40 Handle Ubuntu hardcoded grub cfg
Ubuntu hardcodes grub.cfg to
another location.

Make a stub file as a flag to guide osimage
to know where grub.cfg goes.
2023-08-29 10:57:25 -04:00
weragrzeda f633c93d0f Geit PDU nodeinvntory
Please enter the commit message for your changes. Lines starting
 with '' will be ignored, and an empty message aborts the commit.

 On branch master
 Your branch is up to date with 'origin/master'.

 Changes to be committed:
	modified:   geist.py
2023-08-25 08:27:27 +02:00
Jarrod Johnson 610bc793b7 Merge branch 'master' into ubuntucloning 2023-08-24 10:53:33 -04:00
Jarrod Johnson 85375cc733 Fix hotplug firmware to use rootfs after boot 2023-08-24 10:53:25 -04:00
Jarrod Johnson af4ca64da8 Fix hotplug firmware to use rootfs after boot 2023-08-24 10:53:00 -04:00
weragrzeda 6d87d11f5e my changes to Eaton PDU sensors 2023-08-23 14:28:33 +02:00
weragrzeda 9591ff4718 Merge branch 'master' of https://github.com/weragrzeda/confluent 2023-08-23 14:26:51 +02:00
Jarrod Johnson 439143115e Merge branch 'master' into ubuntucloning 2023-08-22 12:28:36 -04:00
Jarrod Johnson b14b34bdbd Add limited sensor support for Eaton PDUs 2023-08-22 12:28:07 -04:00
Jarrod Johnson 899ce7f055 Correct spelling of hooks directory in Ubuntu cloning 2023-08-17 16:27:45 -04:00
Jarrod Johnson 7e209e412a Make confluent hook executable in ubuntu diskless 2023-08-17 16:16:36 -04:00
Jarrod Johnson 7051f467bb Avoid a deprectationwarning in copytree handling
While trying to address one
deprecationwarning, we
hit another.  Check if the
new function exists and use it,
falling back to distutils if
everything fails.
2023-08-17 14:49:44 -04:00
Jarrod Johnson b88ccc292c Avoid deprecation on distutils with newer python
Unfortunately, python 3.6 needs the distutils version, but we should avoid it altogether
by python 3.10, but by 3.10 the shutil.copytree can do it.
2023-08-17 14:36:38 -04:00
Jarrod Johnson c47066d713 Include ubuntu material in packaging 2023-08-17 14:11:41 -04:00
Jarrod Johnson 8ddcf45e1d Create links for ubuntu20.04 and ubuntu22.04 2023-08-17 14:03:55 -04:00
Jarrod Johnson 53d2b873a2 Package ubuntu 22.04 diskless 2023-08-17 11:28:29 -04:00
Jarrod Johnson bc7dbeebea Add ubuntu 22.04 diskless 2023-08-17 11:16:32 -04:00
Jarrod Johnson 1b2d8a0596 Merge branch 'ubuntucloning' of github.com:lenovo/confluent into ubuntucloning 2023-08-17 11:16:01 -04:00
Jarrod Johnson f3e7d4ab67 Merge pull request #92 from sjtstg/nmcli-autoconnect
Confignet does not set autoconnect with network manager
2023-08-17 08:06:54 -04:00
Simon Thompson b27542ec00 Confignet does not set autoconnect with network manager so disk installed images do not bring up interface on reboot 2023-08-17 10:30:36 +02:00
Jarrod Johnson 58cc9840b3 Prune out any netplan configuration, if exists
To mitigate chance of network configuration
being tanked by image based
net config, mask it when capturing.
2023-08-16 14:28:10 -04:00
Jarrod Johnson 84d23bb1fd Begin work on Ubuntu cloning 2023-08-16 12:00:50 -04:00
weragrzeda 44405baaf3 nodeconfig ntp servers for smms 2023-08-16 14:30:05 +02:00
Jarrod Johnson ae915cd735 Merge pull request #126 from weragrzeda/master
nodelist delimiters
2023-08-15 11:03:48 -04:00
weragrzeda c7a323b370 nodelist delimiters fixed for py2 compatibility 2023-08-15 16:31:38 +02:00
root 9e070a14d4 nodelist delimiters 2023-08-15 15:58:10 +02:00
Jarrod Johnson 189ba525d3 Merge pull request #91 from sjtstg/ansible-play-fix
fix ansible support when multi stage plays are in playbook
2023-08-15 08:38:56 -04:00
Jarrod Johnson 5068cda2cf Catch another sort of exception for non-rpm distributions
subprocess may produce a different sort of exception if
rpm doesn't exist at all
2023-08-14 09:23:00 -04:00
Jarrod Johnson 95c5253944 Remove CIDR prefix length in ubuntu 20 deployment
This produces invalid configuration for subiquity otherwise.
2023-08-11 15:01:55 -04:00
Jarrod Johnson ca2dcd2dbe Reference identity network in ubuntu 20.04
When using identity image, also use identity image
for network configuration.
2023-08-11 14:34:12 -04:00
Jarrod Johnson dba6e7f378 Change Ubuntu 20.04 to be consistent to 22.04
This aims to bring
identity image deployment fully to ubuntu 20.0.4.
2023-08-11 13:44:37 -04:00
Jarrod Johnson 0b7247d386 Fix CentOS 7 routed deployment with identity image
Numerous issues prevented the identity image support from actually running,
correct them.
2023-08-10 16:27:42 -04:00
Jarrod Johnson 75add230b6 Skip API key init on checkonly runs
Checkonly does not require API key, and makes apiclient more dependent
on material that is unlikely to exist early in a deployment.
2023-08-09 11:13:09 -04:00
tkucherera 2c90227f63 "Firmware Update " 2023-08-09 10:48:09 -04:00
tkucherera 0cff70c607 firmware update 2023-08-09 10:37:35 -04:00
Jarrod Johnson 75082c4418 Move up creation of ca.pem 2023-08-03 14:03:36 -04:00
Jarrod Johnson 9a1c9eb43f Improve ssh concurrency on websocket
ssh module was pausing input for the
entire websocket while doing the simple 'write' operation.

Change to background the actual
logon processing,
rather than blocking what should be a fairly trivial write operation.
2023-08-03 09:56:36 -04:00
Jarrod Johnson 89bd798f8b Increasing time again, outlet count didn't factor 2023-08-02 15:20:29 -04:00
Jarrod Johnson bf10e58f00 Bump version
With recent collective changes, bump the version to block connection with
older collective members until upgraded.
2023-08-02 13:43:41 -04:00
Jarrod Johnson cbf2cdcdc5 Scale timeout with number of outlets
Delta PDUs seem to serialize outlet operation.
2023-08-01 16:08:51 -04:00
Jarrod Johnson 987587aaf8 Allow custom auth file to define valid roles 2023-07-26 16:37:55 -04:00
Jarrod Johnson ad25c31d3f Correct error in check_for_yaml function in auth 2023-07-26 16:15:36 -04:00
Jarrod Johnson b1018d648e Hook loading of /etc/confluent/authorization.yaml
This should permit custom roles to be defined.
2023-07-26 16:05:29 -04:00
Jarrod Johnson a18d0f10b7 Clean up stale lvm devices files
During cloning, stale lvm devices file may cause
ugly output.  Remove stale files before proceeding down steps
that trigger lvm warnings.
2023-07-26 07:54:41 -04:00
Jarrod Johnson 65ac3de21b Take EL9 version of image2disk for improvements with parted supervision 2023-07-26 07:26:49 -04:00
Jarrod Johnson c9d9a3cc54 Add EL9 cloning support
Main difference from EL8 is different grub strategy.  To cope, capture
the uuid of new /boot and manipulate the
stub grub.cfg with the right uuid.

In EL8, the efi has the main grub, EL9 changes to have /boot host the 'real' grub,
causing us to have to modify the stub grub.
2023-07-25 17:09:37 -04:00
Jarrod Johnson 957b979dde Reorder imports in configmanager to mitigate circular import 2023-07-24 13:38:44 -04:00
Jarrod Johnson 48c4a2e062 Have reconnects use new TCP connections
Current code was trying to reuse connections that would be useless,
explicitly go to new TCP connections for reconnection.
2023-07-24 12:31:32 -04:00
Jarrod Johnson 285a159ba5 Implement a number of improvements for collective
For one, remove 'non-voting' members from being leaders.
Large number of leader candidates create long delays for
converging on a valid organization.  Further, some treat 'non-voting'
more roughly, inducing the worst case convergence scenario of unclean
shutdown of leader.
Convergence now happens fairly quickly for collectives with large
number of non-voting members.

During initial DB transfer, the leader would be tied up unreasonably
long handling the jsonification of a large configuration.  Offload to a worker
process to allow the leader to continue operation while this intensive, rare
operation occurs.

Reliably run a reassimilation procedure for the lifetime of the leader.
This allows orphaned members to be prompted to join the correct leader.

Serialize the onboarding of a connecting member, and have redundancy more gracefully
paused. This avoids excessive waiting in lock and more deterministic timing
with respect to timeout expectations by the connecting system.
2023-07-24 11:11:39 -04:00
Jarrod Johnson 8ea2ba046e Sort the IP addresses in nodediscover for consistent UI 2023-07-19 16:16:27 -04:00
Jarrod Johnson f16daa44dd Handle older python with addrinfo
While newer python omits '%',
older python includes.  Change to handle
either form.
2023-07-19 16:04:25 -04:00
Jarrod Johnson 03fce4f762 Adjust sys.path logic in macmap and osimage
Ensure the sys.path logic
is before attempting
the relevant imports.
2023-07-19 12:15:01 -04:00
Jarrod Johnson 809099c8f8 Specifically wait for /dev/disk/by-label
When udev is populating the disk hierarchy, it can be a long time
before the 'by-label' is specifically ready.

Wait for that specific entry to come along before continuing to
check if there's an identity image.
2023-07-07 15:32:47 -04:00
Jarrod Johnson a875f0d3e1 Correct syntax error in selfservice 2023-07-06 14:04:49 -04:00
Simon Thompson 6ee9f96e08 fix ansible support when multi stage plays are in playbook 2023-07-06 09:34:38 +02:00
Jarrod Johnson fcc62b7cb7 Improve confluent scanning on newer python
Newer python changed the format of peer[0], adapt to the change
to use the socket info if not available in the peer[0] string.
2023-07-05 16:34:37 -04:00
Jarrod Johnson 11cb47c03e Use natural sort on some self service calls 2023-07-05 16:18:49 -04:00
Jarrod Johnson afc78513a1 Merge pull request #90 from sjtstg/ansible-fixes
Ansible fixes
2023-07-05 16:15:30 -04:00
Simon Thompson 45f22c3e31 when host is not in hosts file, group_vars is not loaded, change logic to emulate host being in hosts file with no groups to ensure group_vars is loaded which permits use of dynamic grouping in plays 2023-07-05 21:25:25 +02:00
Simon Thompson d0f978548e sort directory listing to make ansible plays and script order deterministic 2023-07-05 21:23:55 +02:00
Jarrod Johnson 052d16aa49 Avoid modifying PYTHONPATH
Since there's a possibility of cross-python invocation,
avoid modifying PYTHONPATH
2023-07-05 11:40:00 -04:00
Jarrod Johnson 7ddd2c2e6e Correct mistakes in shebang adaptive behavior 2023-07-05 11:14:32 -04:00
Jarrod Johnson 9186c8142c Fix incorrect reference in the smm validation by certificate 2023-06-28 13:13:26 -04:00
Jarrod Johnson c07248d58e Fix outlet control on Geist PDUs. 2023-06-27 08:04:16 -04:00
Jarrod Johnson 013de4f881 Adapt to ansible python runtime
Unfortunately, python being python, ansible may elect to install under a
different python runtime than confluent.

In such a case, hope that the ansible python can work.

Remove eventlet as a hard requirement, as
that is unlikely to be in ansible python.

This leaves msgpack, which is unavoidable, for now. But if it's in ansible python,
it's fine.
2023-06-26 15:41:44 -04:00
Jarrod Johnson 795b4c513d Rework for connected temperature sensors
PDUs behave differently when a sensor module is
connected. Handle
that difference and
provide the relevant data.
2023-06-26 12:32:45 -04:00
Jarrod Johnson 4056264991 Correct keyname from previous fix 2023-06-23 17:01:50 -04:00
Jarrod Johnson 77c8e93a8d Fix terminal actions on shared websocket
The full complement of functionality was not
interpreted in shared context
2023-06-23 16:33:30 -04:00
Jarrod Johnson 1695e222ec Rename command to nodeapply, by popular demand 2023-06-22 14:16:54 -04:00
Jarrod Johnson b2a793568a Merge pull request #125 from tkucherera-lenovo/master
change timestamp log option from -d to -T
2023-06-22 14:14:59 -04:00
Jarrod Johnson 3ebd43fe0c Bump genesis base version 2023-06-15 09:35:37 -04:00
Jarrod Johnson 2e20e0303f Fix libbpf link 2023-06-15 09:22:52 -04:00
Jarrod Johnson da2df63498 Update location of krb5 2023-06-15 09:20:37 -04:00
Jarrod Johnson 896a4ff1ff Fix spec format 2023-06-14 16:05:08 -04:00
Jarrod Johnson a14effa4f2 Undo change
Realized we need to install related rpm for efivar
2023-06-14 15:57:27 -04:00
Jarrod Johnson 66c79a5f42 Fixup handling of efivar license 2023-06-14 15:52:52 -04:00
Jarrod Johnson 389c37659e Refresh more licensing material in genesis rpm 2023-06-14 15:47:17 -04:00
tkucherera 89af8661da change timestamp log option from -d to -T 2023-06-12 10:51:29 -04:00
Jarrod Johnson 41437c511b Fix when networkmanager breaks one of our connections
This usually happens with ipv6 link local used
in initramfs stage, after networkmanager may
mutilate the ipv6 connectivity.
2023-06-12 08:49:13 -04:00
Jarrod Johnson 75f0aaeee9 Allow session id through header
This permits a client to exert finer grained control
over the session id
than provided by cookie.
2023-06-08 11:30:32 -04:00
Jarrod Johnson 68f9688292 Drop SLP packets with error
Some implementations send
error for services they do not provide.
2023-06-08 08:02:59 -04:00
Jarrod Johnson 67204f79a1 Fix bug where dispatching a request could block all other activity 2023-06-02 11:06:44 -04:00
Jarrod Johnson e9dd7da775 Fix syntax error in el7 identity image support 2023-06-02 08:55:27 -04:00
Jarrod Johnson 8f1be7c905 Fix Python2 compatibility issue with port forwarder 2023-06-01 16:50:06 -04:00
Jarrod Johnson bc684b82b4 Implement identity image based deployment for EL7
Though older, it is still popularly used.
2023-06-01 16:49:17 -04:00
Jarrod Johnson 5e72d40c03 Fix compatibility issue with python2 2023-06-01 13:31:32 -04:00
Jarrod Johnson 7ab2aff7f2 Restore syntax of EL7 deployment
Inadvertent incomplete checkin
broke syntax of EL7, fix to have it
work as-is for now.
2023-06-01 09:20:17 -04:00
Jarrod Johnson c3fc931ba4 Fix python2 compatibility issue for port forwarding
The measure for predictable port numbering
was done with python3 in mind, without consideration
of python2.
2023-06-01 09:18:36 -04:00
Jarrod Johnson 2c61cee72d Merge pull request #124 from Tkucherera/nodeconsole_timestamp
Nodeconsole timestamp
2023-06-01 09:08:33 -04:00
Tinashe 190ec2473b dump log to stfout with timestamps 2023-05-31 17:39:53 -04:00
Tkucherera 9ebb8f27ec Merge branch 'xcat2:master' into master 2023-05-31 17:34:52 -04:00
Jarrod Johnson 0db7d4f9d2 Stall readback of PDU after outlet control
There is some lag after requesting an outlet change and
the outlet state actually changing.
2023-05-26 10:43:04 -04:00
Jarrod Johnson 5d1315098f Enhance and extend check of node relations 2023-05-25 11:14:58 -04:00
Jarrod Johnson fc29ddb913 Improve routed EL8 deployment and add debug shell on tty2 2023-05-24 11:02:23 -04:00
Jarrod Johnson b06b77f5a5 Fix issues with confluent media deployment on multi-nics in routed env 2023-05-23 17:22:38 -04:00
Jarrod Johnson 97a5bf0806 Correct typo in suse 15 diskless boot 2023-05-19 14:50:04 -04:00
Jarrod Johnson 36e61f301a Add a nodefreshen command
This aims to provide the same shortcuts as 'updatenode'
2023-05-18 15:03:29 -04:00
Jarrod Johnson e476c7b9e6 Avoid deprecationwarning in python 3.10+
Newer python is not backwards compatible with
a constant.  Attempt to use new
constant and fallback to teh old one
if unavilable.
2023-05-18 09:20:52 -04:00
Jarrod Johnson a523df80e8 Handle newer SuSE
After SP4, suse drops mkinird requirement.

Switch to dracut -f in such a scenario.
2023-05-16 14:51:27 -04:00
Jarrod Johnson 8f4982e850 Fix build mistake in the cooltera plugin 2023-05-15 08:30:44 -04:00
Jarrod Johnson a167d19441 Add module for cooltera nodesensors 2023-05-10 13:24:20 -04:00
Jarrod Johnson 2237e0e173 Add a retry mechanism for connecting socket
Timing is sensitive during the handshake, catch and retry
if it should fail.
2023-05-10 11:12:29 -04:00
Jarrod Johnson b08b62614a Have proxydhcp recover from faults 2023-05-10 08:44:31 -04:00
Jarrod Johnson e93e4abd83 Add clear error when base profile doesn't exist
If the user specifies a wrong '-b',
indicate clearly that is the case,
and do so early.
2023-05-10 08:40:45 -04:00
Jarrod Johnson 430b24081c Have apiclient timeout if IO hangs up 2023-05-09 16:04:24 -04:00
Jarrod Johnson ec54ecc9cd Fix tiling with different gravity
In some environments, the coordinates may be reported in a
different format.  Handle the different context.
2023-04-28 09:20:31 -04:00
Jarrod Johnson f787461759 Merge pull request #123 from Tkucherera/tmux_reuse
Tmux reuse
2023-04-28 09:18:44 -04:00
Jarrod Johnson 7312d8e092 Provide commented hints for mdns integration
mdns protocol is not currently used, but
put in breadcrumbs for
bringing it alive if
we have an openbmc handler.
2023-04-27 15:51:28 -04:00
Tkucherera 884a6be68c Wkill like command (#1)
* wkill like command fix

* tmux session resuse

---------

Co-authored-by: Tinashe <tkucherera@lenovo.com>
2023-04-27 15:46:40 -04:00
Tinashe a35a7e74c3 tmux session resuse 2023-04-27 15:39:32 -04:00
Jarrod Johnson ffdf799713 Advance mdns support
At this point, the protocol handler
seems up to the task of describing openbmcs
2023-04-27 08:59:39 -04:00
Jarrod Johnson b9d0da0416 Correct mistake in the gathering of valid nodenames 2023-04-26 15:37:08 -04:00
Jarrod Johnson 3fd930137d Begin work on mdns protocol support 2023-04-21 16:14:25 -04:00
Tinashe 71a263366d wkill like command fix 2023-04-21 10:22:10 -04:00
Jarrod Johnson 7b150773df Extend multi-nic guessing to Ubuntu 20/22 2023-04-20 15:45:32 -04:00
Jarrod Johnson 53f4665358 Correct issues in Ubuntu 18 deployment 2023-04-20 14:48:39 -04:00
Jarrod Johnson e5fff430be Explicitly clear logonwaiters on discard of a session
When a session is being discarded, it
may inadvertently hold onto logonwaiters.

The IPMI session may be reused, but the context is new and those
dead contexts can consume memory unreasonably.
2023-04-19 10:22:33 -04:00
Jarrod Johnson 55da173b27 Correct missing parameter in Geist
Geist support was missing a variable in the refactor.
2023-04-19 10:20:34 -04:00
Jarrod Johnson 55a796af82 Correct some errors in the Ubuntu 18 support
An ommited end clause as well
as some bashisms.
2023-04-12 13:23:39 -04:00
Jarrod Johnson 123d190f12 Extend network and deployment server checking for Ubuntu 18.04
When doing network evaluation in ambiguous contexts,
spend some time checking each nic and each candidate target ip address.

This may take longer, but options are limited in a routed context.
2023-04-12 13:04:08 -04:00
Jarrod Johnson 305a3a06d2 Ensure $HOME is set during firstboot
systemd tends not to set environment variables.  However some firstboot
scripts generally expect $HOME to be correct.
2023-04-12 11:22:27 -04:00
Jarrod Johnson 024677d7de Try EL7 to build the old addons 2023-04-07 16:50:20 -04:00
Jarrod Johnson fb31a68818 Add profile.yaml to ubuntu18.04 stock profile 2023-04-07 16:26:32 -04:00
Jarrod Johnson 526a248963 Add ubuntu18.04 to build script in other location 2023-04-07 16:17:37 -04:00
Jarrod Johnson 86d9d6fc2f Add ubuntu18.04 to build 2023-04-07 15:46:29 -04:00
Jarrod Johnson 2bdc53722b Further advance ubuntu 18.04 support 2023-04-07 15:45:31 -04:00
Jarrod Johnson 25b0f45e6f Merge remote-tracking branch 'lenovo/master' 2023-04-07 13:53:44 -04:00
Jarrod Johnson f5b3682c08 Merge pull request #89 from erderial/patch-8
added functionality to check for net.*switch
2023-04-07 13:52:01 -04:00
Jarrod Johnson b7ea27b939 Advance draft Ubuntu 18 support
Get most things automated for the targeted use case.

Still need to handle partitioning and end of install question, add firstboot and add
staged and complete step.
2023-04-06 16:07:55 -04:00
Jarrod Johnson 1fff15677d Add el9bin correctly into build process 2023-04-04 11:55:23 -04:00
Jarrod Johnson 556d858d33 Address extraneous errors during build 2023-04-04 11:27:50 -04:00
Jarrod Johnson 0a02b010c9 Fix esxi build for new build strategy 2023-04-04 11:24:10 -04:00
Jarrod Johnson 08e19fbf6e Provide a sample for fuse3 urlmount
When the time comes to transition, this will be useful.

The challenge is that existing images will likely have a 'distribution'
with fuse2 libs, so this isn't a transition to make lightly.

Definitely should be done for new distributions at least, current
distributions pending further investigation
2023-04-04 10:39:12 -04:00
Jarrod Johnson 2d16d5558c Rework to build everything under el8 or el9 containers specifically
Make the build host less critical of an implementation detail
2023-04-04 10:19:13 -04:00
Jarrod Johnson 7f15e4af27 Change back to fedora
We need fuse-devel for now, since urlmount is written against older fuse
2023-04-04 09:44:04 -04:00
Jarrod Johnson 34313f4041 Change to EL9 for the new-wave util builds 2023-04-04 09:32:25 -04:00
erderial 9bb402a1b8 Update confluent_selfcheck 2023-04-03 10:27:07 +03:00
erderial 13d4c57ee2 changes done as per request 2023-03-31 19:32:43 +03:00
erderial 88c47c9254 added functionality to check for net.*switch
added functionality to check for net.*switch
2023-03-31 16:43:15 +03:00
Jarrod Johnson 181aa876a7 Draft initramfs addons for Ubuntu 18
For older Ubuntu 18, the automated installer is debian-installer.  Derive from the
prototype debian work, with same limitation about more limited network bringup that
we are stuck with from Debian limitations.
2023-03-30 16:36:40 -04:00
Jarrod Johnson a0dbb90c77 Handle mismatched alpha and numeric in hyphenated string
If 123abc-abc123 were attempted, it would produce
a strange error
when it encounters a string compare to number.

Detect the scenario and treat it like similar situations.
2023-03-30 14:21:22 -04:00
Jarrod Johnson cb129789b8 Properly recognize old ubuntu server install media
Older media designed around
debian installer requires
different handling.
2023-03-30 08:33:18 -04:00
Jarrod Johnson 7ac778106e Also skip over failure to broadcast SSDP 2023-03-29 16:55:12 -04:00
Jarrod Johnson f808c542e4 Ignore forbidden transmits on multicast 2023-03-29 16:53:40 -04:00
Jarrod Johnson 2a3bc61be3 Avoid overwriting groups on a redefine
When a node is being redefined, do
not populate groups.

That is only needed when truly defining for first time.
2023-03-29 09:28:52 -04:00
Jarrod Johnson 73fb54ccbc Add more manual licenses to the kernel 2023-03-28 17:02:53 -04:00
Jarrod Johnson 578bd9702a Sample script to install a cert into an XCC 2023-03-24 15:56:26 -04:00
Jarrod Johnson ca5f19a4f1 Sample script for getting a CSR from an XCC 2023-03-24 15:46:21 -04:00
Jarrod Johnson 717df579aa Add firmware to Geist support 2023-03-17 16:02:55 -04:00
Jarrod Johnson 70b973b1cf Refactor measurements in Geist
Use common code
for sensor translation.
2023-03-17 15:34:26 -04:00
Jarrod Johnson 48696ef63d Begin adding sensors to Geist PDUs 2023-03-17 14:37:03 -04:00
Jarrod Johnson ff025989c6 Restore spacing around float in nodesensors
The managed formatting needs
to be padded in the non-csv output.
2023-03-16 17:29:36 -04:00
Jarrod Johnson 872718c658 Add notation about alternate location of ansible plays
Make it known that plays may now be private.
2023-03-16 15:19:15 -04:00
Jarrod Johnson 47af869360 Allow ansible plays to be private
Since the node need not have access,
the ansible plays may be made private instead.

This enables potentially sensitive plays
to be protected.
2023-03-16 15:15:46 -04:00
Jarrod Johnson f256b1cd4e Handle more complex ansible configuration
Some plays expect the
inventory from /etc/ansible, detect
if that inventory *could* apply, use if it can.

ansible users generally anticipate leveraging the implicit '.' in the role
path,
chdir to meet that expectation.

'become' in the play without 'become_user' can upset ansible runtime.

Since we are already root, we will just ignore the implicit 'become', since we already
match that behavior.
2023-03-16 13:24:46 -04:00
Jarrod Johnson bfe03e6e01 Fix erronously dragging in CIDR to IPv4 configuration 2023-03-14 16:55:20 -04:00
Jarrod Johnson 8dc3dfd20c Limit TRYNIC to only one NIC in ubuntu deployment 2023-03-14 15:36:24 -04:00
Jarrod Johnson 0cc588f8e9 Carry nic detection through to bottom of Ubuntu 2023-03-14 15:24:37 -04:00
Jarrod Johnson e12578b6ac Use media net config when media deployed 2023-03-14 13:32:20 -04:00
Jarrod Johnson 0366bbd26f Place apikey where expected 2023-03-13 17:00:35 -04:00
Jarrod Johnson 5f4ab5ff80 Fix path to hmacfile
Since we are running
outside of chroot, need to adjust the $()
substitution.
2023-03-13 16:21:25 -04:00
Jarrod Johnson 88a6bccf12 Use b64 alphabet for b64
While POSIX hates +, b64 needs +
2023-03-13 16:20:17 -04:00
Jarrod Johnson 52c3e9d515 Do not care about port, let kernel decide 2023-03-13 11:19:11 -04:00
Jarrod Johnson 50a4ee2c6d Have a quick sample script to get LLA of USB nic peer 2023-03-13 11:15:31 -04:00
Jarrod Johnson 15ff24fccd Correct syntax errors in auth.py 2023-03-10 16:38:47 -05:00
Jarrod Johnson d9cc9112f4 Add identity image deployment to Ubuntu
Support the api arm token
and media network
config for Ubuntu.
2023-03-10 16:23:48 -05:00
Jarrod Johnson 5418d9ea97 Place a common script for setupssh 2023-03-10 16:05:29 -05:00
Jarrod Johnson 2aeade1e74 Merge pull request #88 from erderial/patch-6
updated with custom yaml file for auth
2023-03-09 15:48:12 -05:00
erderial 85f9dc12fb Update auth.py 2023-03-09 22:38:37 +02:00
erderial 56dea2422a Update auth.py 2023-03-07 21:08:01 +02:00
Jarrod Johnson 8b89232922 Do not get collective member when collective doesn't exist 2023-03-06 16:59:07 -05:00
Jarrod Johnson 22c464e092 Only add self to collective if self not yet in collective
Previously, it was safe to just do all the time, but now it may lose
the role.
2023-03-06 16:49:03 -05:00
Jarrod Johnson 4d9b11bc55 Fix quorum when there is no collective yet 2023-03-06 16:38:09 -05:00
Jarrod Johnson baa365fcac Implement non-voting collective members
Provide for applications
where only a small subset of collective
members should be
considered to count
toward whether the collective
can proceed.

Commonly, 'service' nodes may
be numerous to do work, but may all want to go offline
during a maintenance window.
2023-03-06 11:56:15 -05:00
Jarrod Johnson a385b1e93d Try strategy to have confignet run
confignet is special, it is designed
to work when networking
isn't right.  So have it run during firstboot
in case post fouled up
the network for firstboot.
2023-02-28 12:12:36 -05:00
Jarrod Johnson 733b6853dd Up newly added interfaces as a matter of course 2023-02-28 12:04:20 -05:00
Jarrod Johnson b4182cd4b5 Fix formation of error message
Use format to take in the parameters regardless of type
2023-02-27 14:55:01 -05:00
erderial cf2f5aac7b Merge branch 'lenovo:master' into patch-6 2023-02-27 18:27:39 +02:00
Jarrod Johnson 9f7e53701e Avoid latching onto USB nic in a vswitch as 'the nic'
In esxi, some builds may have USB nic brought up in a vswitch.

Detect and avoid that scenario.
2023-02-27 10:43:40 -05:00
erderial 3b9f9abdd9 Merge pull request #2 from erderial/erderial-patch-1
updated auth.py with some changes
2023-02-27 17:36:20 +02:00
erderial b800aa032e updated auth.py with some changes
updated auth.py with some changes. Need to add the check_for_yaml() function to main.py as well
2023-02-27 17:10:17 +02:00
Jarrod Johnson 70d8a1059c Consistently treat bytes as bytes in ssh
In Python3 systems,
there would be confusion
about bytes versus str.

Fix this so that ssh can work more consistently.
2023-02-24 15:47:20 -05:00
Jarrod Johnson 59b07665ab Modify float formatting again
Make sure at least one decimal is in a float.

Maximum precision of 5 past.
2023-02-24 12:03:43 -05:00
Jarrod Johnson 5ea214a726 Use eventlet subprocess
sshutil uses eventlet subprocess,
making calledprocesserror
hard to catch.

Adjust to consistently use same
subprocesss module.
2023-02-22 16:34:13 -05:00
Jarrod Johnson b99034f539 Improve reliability of collective join
While servicing an enrollment,
there's a window for a collective
member to be 'defined' but not
yet active, meaning quorum may transiently be lost as multiple enrollments progress.

Serialize enrollments by holding the enrollment process open.

Also, there is a chance that a transient transfer error may occur during loading
of the DB.  In such a case, restart
the connection rather thn aborting.
2023-02-22 16:11:38 -05:00
Jarrod Johnson 6df2e822a5 Correct api call in discovery 2023-02-22 09:34:32 -05:00
Jarrod Johnson 2379f6f90f Change nodesensors format of float
Floats are either unnecessarily long
in normal output, or too unconstrained in CSV output.

Normalize to as many digits as 'makes sense' up to 5 digits.

5 miight seem a bit much, but one common metric is kWh, which may need
that precision over short intervals.
2023-02-22 08:41:46 -05:00
erderial 8940247164 updated with custom yaml file for auth
Added 2 new function to check if the custom yaml file exists - /etc/confluent/authorize.yaml - and one to update the _allowbyrole and _deniedbyrole vars accordingly.
2023-02-21 15:13:17 +02:00
Jarrod Johnson 77ba0acee6 Merge pull request #122 from Tkucherera/nodeconsole-kill
nodeconsole <noderange> kill: added functionality for closing open win…
2023-02-16 16:37:07 -05:00
Tinashe b2c773bb84 nodeconsole <noderange> kill:added functionality for closing open windowed consoles 2023-02-16 15:54:21 -05:00
Jarrod Johnson 241800b1c9 Restore filename-only import
The open file handle as implemented
could not pass to the subprocess.

Rather than figure out how to open
and pass the filehandle,
simply let the subprocess
independently open the file
if it isn't passed.
2023-02-16 09:13:05 -05:00
Jarrod Johnson abc639e32b Preferentially support HTTPS on Eaton PDU
While Eaton does not do HTTPS by default,
it can be configured to do so.

Support when available.

Mitigate downgrade attack by
stickying the cert fingerprint.
If fingerprint is present, then refuse
to even think about port 80.
2023-02-15 17:03:35 -05:00
Jarrod Johnson 90af99e864 Add more clear error on syncfile mistake
If a bad node was included in
a syncfile, the error was highly misleading.

Provide a more clear indicaiton of the problem on failure.
2023-02-14 14:53:40 -05:00
Jarrod Johnson 09ce824c85 Fix bad lookup attempts on slashed addr
While this should in theory be
harmless, it exacerbates some
DNS setups that would look
up the normal result quickly,
but would stall on
a bad lookup.
2023-02-14 14:53:40 -05:00
Jarrod Johnson 9c1e7a7142 Allow interfaces to supersede default
In some scenarios, the 'default'
interface is overlapped by another connection, either
identical or as a superset in a bond.

Whittle down the default
interface if superseded
to mitigate duplicate interface setup.
2023-02-14 14:53:40 -05:00
Jarrod Johnson 36195198a6 Add fallback for newer msgpack
Newer msgpack refuses the encoding argument, use raw=False instead.

Further, newer msgpack refuses to accept int as key by default.
Opt into it as the risk is hash collision due to msgpack int being used directly, and
we aren't dealing with untrusted
peer (we only talk to ourselves).
2023-02-14 14:53:40 -05:00
Jarrod Johnson 3798a33213 Merge pull request #121 from Tkucherera/nodeconsole
nodeconsole documentation: passthrough options
2023-02-14 08:45:43 -05:00
Tinashe 251b307bd7 nodeconsole documentation: passthrough options 2023-02-14 08:27:25 -05:00
Jarrod Johnson bb7a72db65 Fix for ipv6 deployment
Need to avoid double-bracketing of the server and also disable globbing
so curl does not mistake the ip address for a glob attempt.
2023-02-13 09:36:42 -05:00
Jarrod Johnson fcde113e08 Add a check of dns.domain to selfcheck for node 2023-02-08 14:45:16 -05:00
Jarrod Johnson a02f617b3d Add DDR5 dimm to nodeinventory CLI output 2023-02-07 14:01:18 -05:00
Jarrod Johnson 7f1ac92fc9 Store mgr from confluent= specificate 2023-02-01 16:51:21 -05:00
Jarrod Johnson 8cf97833ab Fixes for certificate directed discovery 2023-02-01 13:09:40 -05:00
Jarrod Johnson 3e747069d9 Try to get verified bay from SMMs
With V3 systems, we can now ask
the SMMs for the certificates
and use that for a verified
measurement, regardless of
whether the XCC is returning
the correct bay number.
2023-02-01 12:57:27 -05:00
Jarrod Johnson c687da4d5f Tweak architecture override on import 2023-01-31 15:57:41 -05:00
Jarrod Johnson 340ccc422c Specify check for arch override of addons.cpio
For now, keep using x86_64 as
default, but allow overrides
for other architectures.

One day it may be cleaner to move all addons.cpio to
arch specific subdirs.
2023-01-31 15:27:45 -05:00
Jarrod Johnson 2c3afac576 Restructure aarch64 addons
Avoid tripping over current copy over, prepare
for smarter selection by architecture.
2023-01-31 15:10:49 -05:00
Jarrod Johnson 8e1cc63ac0 Correct spelling of keyword argument in ipmi 2023-01-31 15:00:22 -05:00
Jarrod Johnson dc6c7c1acc Make sure both el8 and el9 binaries are packed 2023-01-31 13:29:24 -05:00
Jarrod Johnson 5c309db47c Further ARMv8 support
Handle aarch64 differences in
at least some distributions.
2023-01-31 11:20:40 -05:00
Jarrod Johnson 976e9ef563 Bump version on genesis 2023-01-31 09:10:23 -05:00
Jarrod Johnson 0efd2a4d74 Fix the amended license gathering 2023-01-31 08:58:56 -05:00
Jarrod Johnson 424830471d Note how to fetch srpms associated with genesis 2023-01-31 08:54:03 -05:00
Jarrod Johnson 23f33a8420 Revamp license gathering for genesis 2023-01-31 08:52:32 -05:00
Jarrod Johnson 521a58c1d9 Have a utility to generate NOTICE from tmux
tmux basically defers to the c files, so
generate a NOTICE file from c files.
2023-01-31 08:37:42 -05:00
Jarrod Johnson ce375a1162 Merge pull request #120 from Tkucherera/master
Adding missing imports
2023-01-30 14:48:05 -05:00
Tkucherera caee136012 Merge branch 'xcat2:master' into master 2023-01-30 14:15:53 -05:00
Tinashe 2e283f3442 nodeconsole: missing imports time and socket 2023-01-30 14:13:44 -05:00
Jarrod Johnson 2b01d9fbfa Properly store all candidate host ip addresses
This is needed to ensure that mis-detected primary ip
falls through to another viable ip
2023-01-30 12:40:40 -05:00
Jarrod Johnson 627bc9ffe3 Modify pkglist for aarch64 2023-01-27 12:14:37 -05:00
Jarrod Johnson 3e71e103b1 Fix unpacking of el8 and el9 built sources 2023-01-27 10:47:27 -05:00
Jarrod Johnson a90cd8515e Tweak osdeploy for ARM setup 2023-01-27 10:43:29 -05:00
Jarrod Johnson 284d042afe Merge pull request #119 from Tkucherera/master
nodeconsole windowed and tiled functionality
2023-01-27 09:33:45 -05:00
Tinashe 2cc134adeb nodeconsole: allow for passthrough args 2023-01-27 09:30:46 -05:00
Jarrod Johnson 02e242ec4e Restore link local cert in apiclient 2023-01-27 09:13:47 -05:00
Jarrod Johnson 1777223232 Fixes for osdeploy arm ipxe init 2023-01-27 08:40:31 -05:00
Jarrod Johnson 648290ffbc Begin implementing aarch64 deploy support 2023-01-27 08:00:38 -05:00
Tinashe c9b72225a9 nodeeventlog timeframe documentation 2023-01-26 10:37:30 -05:00
Tinashe 3433635e9b nodeeventlog: timeframe option 2023-01-26 10:16:33 -05:00
Tkucherera 7a6c4fc5b2 Merge branch 'xcat2:master' into master 2023-01-26 10:05:04 -05:00
Tinashe f176a836ae nodeecentlog: add timeframe option 2023-01-26 10:01:02 -05:00
Jarrod Johnson ce324e90f7 Draft spec to generate addons-aarch64 files 2023-01-25 12:54:03 -05:00
Tinashe 23ea53ab55 console geometry 100x31 2023-01-24 11:18:21 -05:00
Jarrod Johnson d14d28caf8 Confirm TLS connectivity when scanning hosts
In certain environments, Confluent may have an IP address that
is fake, but then there is elsewhere with that same IP for real.

To mitigate this, follow up basic connectivity with proof of having
an associated certificate.
2023-01-24 08:22:00 -05:00
Jarrod Johnson 0008998680 Add api method to request all mac data
This will provide easy way for
client to get FDB data, potentially
for use in conjunction with discovery data.

For now, leave LLDP out, as that isn't currently cached
at the confluent layer.
2023-01-23 13:37:29 -05:00
Jarrod Johnson 2e059b5887 Make an API for getting full discovery data in one fetch
This makes for faster nodediscover being possible, also
makes web management of the data easier
2023-01-23 11:47:33 -05:00
Jarrod Johnson 792e6472e4 Fix IPv6 addresses_match
fe80:: could be submitted during
collective startup, handle that problem appropriately.
2023-01-23 11:24:25 -05:00
Tinashe b965f9b758 nodeconsole windowed and tiled functionality 2023-01-20 16:41:56 -05:00
Jarrod Johnson a522e17a63 Merge pull request #118 from Tkucherera/master
nodeeventlog man page -l option
2023-01-20 14:49:11 -05:00
Tinashe 9f3b934ea4 nodeeventlog man page -l option 2023-01-20 14:24:32 -05:00
Jarrod Johnson 680ca2c4a2 Merge pull request #117 from Tkucherera/master
nodeeventlog: return last n entries
2023-01-20 12:51:16 -05:00
Tinashe c3d0d255d3 nodeeventlog: -l return last n lines for each node 2023-01-20 12:13:15 -05:00
Tinashe 46d0a8d222 nodeeventlog: return last n entries 2023-01-20 10:09:52 -05:00
Jarrod Johnson 75f020f53c Have apiarmed continuous be properly respected for shared secret
Remote media was erroneously being invalidated, despite user opting
out of the strict security.
2023-01-19 14:54:18 -05:00
Jarrod Johnson c09e8448c2 Change to POSIX compliant range
POSIX allows ., but does not allow +.  This was a problem with EL 8.4 libxcrypt,
though is not a problem otherwise.
2023-01-19 14:53:35 -05:00
Jarrod Johnson 01f939b871 Have SuSE path also not be bothered by inability to restart web service 2023-01-18 08:50:30 -05:00
Jarrod Johnson 1f23750356 Add affluent detection to confluent
Affluent agent will now have an SSDP
response.  Add support for at
least recognizing and presenting
this in the discovery data.
2023-01-17 15:11:12 -05:00
Jarrod Johnson d1265af828 Handle more errors
subprocess may throw other errors that aren't calledprocesserrors,
in newer python versions.  Handle the case more broadly.
2023-01-17 10:04:10 -05:00
Jarrod Johnson 0929f059e2 Increase track size in dir2img
Larger images still run afoul of track limits
in mtools.  Make tracks 4 times as big
to lower number of required tracks.
2023-01-17 10:02:51 -05:00
Jarrod Johnson 40c3f2da53 Actually display deployment state, when available 2023-01-13 13:02:17 -05:00
Jarrod Johnson 51e53405d8 Add attributes for profiles to report state
Profiles may want to report things
like success and error
2023-01-13 12:54:21 -05:00
Jarrod Johnson d644d34b60 Add '-s' to nodeinventory
This allows a quick command to
get attributes into confluent
for manually added nodes,
without having to go through 'discovery' process.
2023-01-13 12:29:36 -05:00
Jarrod Johnson 7f31ae5b57 Fix syntax error 2023-01-13 11:15:51 -05:00
Jarrod Johnson a09e1a3f8b Handle IPv6 not set on IPMI nodes 2023-01-13 11:07:13 -05:00
Jarrod Johnson 50c073670d Explicitly declare Textmode during autoconsole
This enables a workable console during text install,
while also allowing graphical to run
2023-01-13 10:54:29 -05:00
Jarrod Johnson bc452b9b9a Restore role-less group
If a group is missing a role,
coerce it to administrator
2023-01-13 10:01:52 -05:00
Jarrod Johnson 453d1f9ceb Add IPv6 configuration support
For redfish and IPMI devices,
support new IPv6 static configuration
controls
2023-01-13 10:01:28 -05:00
Jarrod Johnson feed125c86 Fix restoration of old confluent db
Old confluent DB may have None in role. This is no longer
allowed.  Restore such entries by coercing them to 'Administrator'
which is how old confluent treated such users.
2023-01-12 08:38:55 -05:00
Jarrod Johnson 03fcd3f568 Fix indentation mistake in add_local_repositories 2023-01-11 09:53:01 -05:00
Jarrod Johnson 0e18a0c141 Fix routed nodeconfig in nodediscover 2023-01-09 08:55:46 -05:00
Jarrod Johnson cc0962f5e5 Fix add_local_repositories in v6 environment 2023-01-06 15:35:36 -05:00
Jarrod Johnson 57b6d8677b Fix syncfiles compatibility with IPv6 2023-01-06 09:33:06 -05:00
Jarrod Johnson 989066920d Fix formatting of the confluent2hosts man page 2022-12-16 09:49:19 -05:00
Jarrod Johnson d2a2383c92 Add man page for confluent2hosts 2022-12-16 09:44:52 -05:00
Jarrod Johnson 92a4b81247 Fix sample featuring non-existant attribute 2022-12-15 16:04:48 -05:00
Jarrod Johnson 130fce0320 Prevent bulk renames from stomping on itself
If multiple things try to renam to the same thing, block the action.
2022-12-15 15:42:10 -05:00
Jarrod Johnson 367854128a Several fixes for imgutil
imgutil had a number of issues
contending with a distribution-less
image being packed/unpacked.
2022-12-14 16:51:39 -05:00
Jarrod Johnson a5ee3a425f Provide full path to DSA key for deletion 2022-12-14 16:15:30 -05:00
Jarrod Johnson 34741cfaf2 Clear terminal after full draw
A resize may need cleanup below
the output.
2022-12-14 16:14:34 -05:00
Jarrod Johnson 9dce7d31ea Change screensqueeze to render in-line
Try to avoid clear screen and work within a logical
area under the command being run
2022-12-14 15:47:33 -05:00
Jarrod Johnson f524114e56 Remove DSA key from install 2022-12-14 13:00:24 -05:00
Jarrod Johnson 511fbe987b Suppress redundant output when writing to non-tty 2022-12-12 13:41:48 -05:00
Jarrod Johnson 7ccd1a42cd Add r8152 driver to diskless/genesis
It is a popularly requested USB ethernet device for network booting
2022-12-12 12:59:37 -05:00
Jarrod Johnson 848e5acea1 Make nfs available to diskless
This allows nfs based flows to be built by users
2022-12-12 12:35:00 -05:00
Jarrod Johnson e4dc57a810 Fix syntax of grep 2022-12-09 14:57:47 -05:00
Jarrod Johnson 0d5f48b116 Be more patient and more noisy about DHCP attempt over time 2022-12-09 13:05:10 -05:00
Jarrod Johnson 0a9fd8351b Correct firstboot on remote media deployment 2022-12-09 11:19:06 -05:00
Jarrod Johnson f55c25a52c Avoid mangling ipv4 in url in media deployment 2022-12-09 10:59:50 -05:00
Jarrod Johnson 93f6641a16 Carry deployment hook through to firstboot 2022-12-09 10:33:23 -05:00
Jarrod Johnson 7e2ae4de62 Restore ipv4-only media based deployment 2022-12-09 10:11:09 -05:00
Jarrod Johnson 82fe68216a Save deployer to mgr when media directed
Pre-empt the IPv4/v6 fallback designed.
2022-12-09 09:04:11 -05:00
Jarrod Johnson fb98cbaa4a Restore fallback to plain MANAGER specification
This is used in the media based deployment
2022-12-08 09:28:32 -05:00
Jarrod Johnson 2d5a016ad4 Tweak various issues for static analysis.
For autocons, though it's copying from a static source, use strncpy anyway,
despite the length being hardcoded already.  This makes static analysis happier.

Terminate the buff with a NULL.  This is superfluous as the strcpies that preceed
are guaranteed to null terminate, or exit the program.

In clortho, free(tmps), which is a valid leak, though clortho isn't long running.
Also, explicitly return 0, which is ultimately returned by main().

Static analysis could not figure out that padneeded implies that keylen is short of
chunk size, so change the check to be expressly the scenario that static analysis
was worried about directly, rather than indirectly.

Hint to static analysis that we don't care about the time as a time value by masking the
lower 32 bit explicitly.  This was already happening, but static analysis was afraid
that we wanted this as time instead of just some mutating value.
2022-12-06 15:35:49 -05:00
Jarrod Johnson 0cb3e3d216 Add rebase to osdeploy man page 2022-12-02 11:35:10 -05:00
Jarrod Johnson adbf96f23f Use bytearray in PXE processing
Python 2 and 3 are inconsistent
with how they treat memoryview,
but they are consistent on bytearray
treatment

Since rqv is merely a cheaply sliceable view of rq, use rq directly
for functions where the difference
between 2 and 3 would matter.
2022-12-02 11:24:00 -05:00
Jarrod Johnson c3576e4bd3 Enhance tab completion and extend some documentation and usage 2022-12-02 08:23:21 -05:00
Jarrod Johnson 84783c0c19 Add error check to noderange for nodedeploy 2022-12-01 14:09:25 -05:00
Jarrod Johnson 58a4c22aa2 Allow custom privilege levels through messages layer
If a user has created custom roles, designate custom. as
a prefix to indicate they really
mean what they say
2022-11-30 11:40:36 -05:00
Jarrod Johnson dce80de9d5 Correct syntax error in sample script 2022-11-30 11:09:57 -05:00
Jarrod Johnson c0f669cbdf Add DHCP bringup to confluent= el8diskless
For routed, if user specifies confluent=, use that as a clue to
initiate a dhcp transaction to
facilitate routed requests.
2022-11-30 11:09:39 -05:00
Jarrod Johnson 2e20341ea0 Have imgutil exec attempt to provide source repos 2022-11-30 10:15:12 -05:00
Jarrod Johnson 57d01ddcaa Base all web forwarding from 3901
This makes the web forwarding more predictable for
firewall rules
2022-11-28 15:17:59 -05:00
Jarrod Johnson 05bbd8f63a Further refine pxe logging and fix external DHCP pxe 2022-11-22 11:08:45 -05:00
Jarrod Johnson bb54ca0f8f Fix mistake caused by erant paste 2022-11-22 09:31:39 -05:00
Jarrod Johnson 2c7b58d47a Put brakes on configuration if no gateway and target is remote
This configuration would certainly destroy remote connectivity.
2022-11-22 09:24:18 -05:00
Jarrod Johnson 7341164f36 Have pure proxyDHCP trigger discovery and logs
For users that fully delegate core DHCP, provide discovery and
logging for PXE as it comes in.
2022-11-22 09:09:21 -05:00
Jarrod Johnson 626aca0691 Implement proxyDHCP remote operation
Provide means to function if we are
only the proxyDHCP service, delegated
from DHCP server.
2022-11-21 13:26:37 -05:00
Jarrod Johnson 132e40cdcb Fix syntax mistak in attribute update 2022-11-21 10:18:58 -05:00
Jarrod Johnson 90a8d80b45 Rework trusted networks to attribute
This allows  more flexibility and less oddity with how remote subnets are treated.
2022-11-21 09:57:27 -05:00
Jarrod Johnson 9eb2d25e37 Fix the subscribe/unsubscribe behavior in nodediscover client 2022-11-18 14:30:10 -05:00
Jarrod Johnson 963b35cd32 More aggressive timeout redfish checking
To make scans go faster, be more aggressive in
giving up on non-responsive targets.
2022-11-18 14:24:58 -05:00
Jarrod Johnson 9837ad7932 Add multi-address registration
This enables scanning a range or subnet
2022-11-18 14:14:31 -05:00
Jarrod Johnson 2c1e88d927 Provide usage when arguments omitted for nodegroupattrib 2022-11-17 14:04:16 -05:00
Jarrod Johnson 4af1dd5dd3 Omit extraneous related rpms 2022-11-15 11:46:52 -05:00
Jarrod Johnson b6487df32a Add missing ipmitool COPYING file to build 2022-11-14 16:20:42 -05:00
Jarrod Johnson cee3943e4d If node was found by key lookup, skip the sysdisco attempt 2022-11-14 15:26:52 -05:00
Jarrod Johnson 03e632b630 Add register to nodediscover command
This connects the remote registration
api to the usual CLI usage
2022-11-14 09:42:59 -05:00
Jarrod Johnson 6a9024d87e Fix bad/unsupported targets in registration 2022-11-11 15:00:59 -05:00
Jarrod Johnson 9fa8a7124e Pull the typical XCC scanning to remote registration path 2022-11-11 14:33:54 -05:00
Jarrod Johnson c6079a1ee6 Add ability to register remote systems in discovery
To start with, support Lenovo XCC systems
2022-11-11 12:16:41 -05:00
Jarrod Johnson ed94804b90 Change timezone substitution strategy
This uses a more self-evident breadcrumb to intuitively override
for users not wanting to use the confluent facility for timezone
adjustment.

There are other 'peculiar' substitutions that may prefer a breadcrumb
but they may require structure that would be tricky to implement
while also passing validation.
2022-11-10 08:57:04 -05:00
Jarrod Johnson 35abe0b9ad Fix IPv6 address support in geist plugin 2022-11-09 15:11:25 -05:00
Jarrod Johnson 81c14db9dd Pull EL8 IPv6 diskless to EL8 2022-11-08 16:37:00 -05:00
Jarrod Johnson 9179e02464 Fix diskless imgutil compatibility issues with EL9 2022-11-08 14:25:21 -05:00
Jarrod Johnson 48ac07e71d Correct placement of initialization of the confluent_websrv variable 2022-11-08 11:33:43 -05:00
Jarrod Johnson 635b559c87 Fix IPv6 syntax for ssh certs in EL8 diskless 2022-11-08 10:51:31 -05:00
Jarrod Johnson 6865e3259e Detect broken ipv4 and try ipv6 2022-11-08 09:45:08 -05:00
Jarrod Johnson 3d37692360 Add IPv6 to the imageboot script for EL profiles 2022-11-08 09:16:20 -05:00
Jarrod Johnson 20e6e1e521 Refresh functions to cope with v6-only usage 2022-11-08 08:52:29 -05:00
Jarrod Johnson 645abc2db7 Add [] to escape ipv6 prior to fetch of functions 2022-11-07 13:54:17 -05:00
Jarrod Johnson 578b05604b Reject fe80:: as always not same
For our purposes, this same-subnet check doesn't
apply to link-local
2022-11-07 13:50:45 -05:00
Jarrod Johnson e6e89bcee5 Steer v6 boot appropriately to v6 server 2022-11-07 13:25:26 -05:00
Jarrod Johnson a21af719c2 Get ipv6 compatible deploycfg api call 2022-11-07 11:43:51 -05:00
Jarrod Johnson 13f3d4c1a6 First pass at adding ipv6-only boot for diskless el8 2022-11-07 11:07:45 -05:00
Jarrod Johnson bd416f5000 Fix ipv4-free configuration in netutil 2022-11-03 14:43:49 -04:00
Jarrod Johnson ca1f459364 Add remote scan to autosense startup 2022-11-03 13:59:14 -04:00
Jarrod Johnson 7e02987a8c Extend rescan to cover remote switches 2022-11-03 13:31:57 -04:00
Jarrod Johnson 327a45ef33 WIP toward rescan hitting the renotify on subscripbed switches 2022-11-03 10:49:58 -04:00
Jarrod Johnson f1a0d22fe5 Fix subscription handling for the discovery api 2022-11-03 09:58:57 -04:00
Jarrod Johnson 1e78f11c2b Fix nodediscover CLI for subscribe/unsubscribe 2022-11-03 09:38:39 -04:00
Jarrod Johnson 7561b68b57 Rework subscriptions API
It's clear that the service will need
to explicitly track subscriptions
to enable rescan, for example,
and thus might as well restructure
the API around this information.
2022-11-03 09:21:15 -04:00
Jarrod Johnson a6090877ff Implement subscribe/unsubscribe in nodediscover
This provides a self-evident entry point from
CLI to extending the discovery to
affluent switches that support it.

This function will work with newer affluent
and Lenovo XCC2 systems.
2022-11-01 14:16:00 -04:00
Jarrod Johnson eec20a6457 Rename discovery remote to subscription
This will implement a consistent vocabulary
2022-11-01 13:51:54 -04:00
Jarrod Johnson 52de243090 Merge pull request #116 from andywray/master
Update nodeconsole -w to work with arbitrary terminal types
2022-11-01 13:40:11 -04:00
Andrew Wray 9742a5d81b Merge branch 'master' of https://github.com/lenovo/confluent 2022-11-01 13:30:18 -04:00
Andrew Wray e20e978e04 Add xterm as default terminal for nodeconsole -w 2022-11-01 13:25:20 -04:00
Jarrod Johnson 299785a7b8 Add manifest data for diskless images 2022-11-01 13:01:14 -04:00
Andrew Wray 8a3105cd51 Update nodeconsole -w to work in arbitrary terminal programs. 2022-11-01 11:29:41 -04:00
Jarrod Johnson 4802c52854 If attempt to auto-restart service, reduce severity of result
Provide feedback as a warning rather than aborting the command entirely
2022-11-01 10:05:24 -04:00
Jarrod Johnson 4a3834b481 Add missing sample syncfiles to suse15 profiles 2022-11-01 09:26:17 -04:00
Jarrod Johnson 13065a3c9d Add missing bits of suse 15 diskless profile 2022-11-01 09:10:17 -04:00
Jarrod Johnson 817038c6cf Specify the valid values for apiarmed
Further, add more warning text around apiarmed, as it is a serious security
decision to take on continuous.
2022-11-01 08:37:03 -04:00
Jarrod Johnson e0feb104ff Add facilities to subscribe/unsubscribe from discovery agents
This connects the new affluent discovery facility
to local discovery view.
2022-10-28 16:58:30 -04:00
Jarrod Johnson 3afd6ecb5d Temporarily enable IPv6
NetworkManage may go further out of it's way disabling ipv6, disable using proc to
overcome that
2022-10-28 12:10:03 -04:00
Jarrod Johnson fd14221ab5 Avoid truncating console logging of firstboot
With significant firstboot output, there was a tendency
for tail to be killed before it relayed all the content.

Change to run the firstboot in a subshell in the background,
and have tail explicitly run until that subshell naturally
exits and then tail will cleanly exit
2022-10-28 09:30:12 -04:00
Jarrod Johnson d534f29c57 Implement fastpath for delegated discovery
When an enlisted discovery agent
notifies, skip slow searches and use
the agents information directly.
2022-10-27 15:42:58 -04:00
Jarrod Johnson f6d8294e83 Check IP viability before commencing configuration
This avoids a pointless partial configuration from proceeding.
2022-10-27 15:41:13 -04:00
Jarrod Johnson 6c806c8171 Fix tentative path for real path 2022-10-27 10:03:18 -04:00
Jarrod Johnson 8bf067cac8 Fix issues in the auth nets logic 2022-10-25 12:52:22 -04:00
Jarrod Johnson 0d2a1b856b Fixes for the auth_nets configuration 2022-10-25 12:35:18 -04:00
Jarrod Johnson 4864d6abb0 Add mechanism to extend authentication to remote networks
This allows user to designate certain networks to be treated as
if they were local.

This enables the initial token grant to be allowed to a remote network.

This still requires that the api be armed (which should generally be a narrow window of
opportunity) and that the
request be privileged, it
just allows remote networks to be
elevated to be as trusted as local.
2022-10-25 11:26:44 -04:00
Jarrod Johnson 5794cd5d12 Modify firstboot to fall through to ipv6 if ipv4 failed 2022-10-25 08:21:42 -04:00
Jarrod Johnson 9964b33414 Fall back to v6 in more scenarios 2022-10-24 17:03:00 -04:00
Jarrod Johnson be2959f365 Fall through to ipv6 if v4 is blank 2022-10-24 16:42:02 -04:00
Jarrod Johnson 31bf8f2a11 Numerous fixes for the cmdline directed deployment in EL8 2022-10-24 16:13:59 -04:00
Jarrod Johnson 6df9ca54ca Ensure access to dracut utility funcitons in pre-trigger hook 2022-10-24 15:52:40 -04:00
Jarrod Johnson c57090a670 Correct order of find and replace strings in by-mac boot 2022-10-24 13:26:06 -04:00
Jarrod Johnson 29ad1bd57e Add various ways to look up boot file 2022-10-24 12:31:23 -04:00
Jarrod Johnson f245f5cac5 Inject a hook for cmdline to specify confulent server
This enables a more manual approach
to indicate the deployment server.

This carries the assumption that a
normal OS autonetwork config
will get the node to the right network.

This is one step toward enabling a scenario where the target is remote and the DHCP is not going to relay, but instead the deployment feeds the DHCP a confluent URL entry point to get going.

Using this parameter precludes:
-Enhanced NIC auto selection.  If the OS auto-selection fails to
identify the correct interface, the profile will need nic name baked in.
-Auto-select deployment server from several.  This will mean that any
HA will require IP takeover be externally handled

This is of course on top of the manual process of
indicating confluent in kernelargs.
2022-10-17 13:07:18 -04:00
andywray 3da2ac61cc Update nodeconsole man page with more -w examples 2022-10-15 21:52:14 -04:00
andywray a25443c81d Update help, check for null env variable 2022-10-15 21:29:56 -04:00
andywray bd00059667 Update man page for -w with arbitrary terminal types 2022-10-15 21:09:31 -04:00
andywray 2c58320f32 Update nodeconsole -w to work with arbitrary terminal types 2022-10-15 21:03:35 -04:00
Jarrod Johnson 167ef0ae33 Merge pull request #87 from erderial/patch-5
Changed the Popen to skip the communication
2022-10-14 11:06:57 -04:00
erderial 8827e7efe8 Changed the Popen to skip the communication
Changed the Popen to skip the communication
added escape method
2022-10-14 18:03:51 +03:00
Jarrod Johnson 4ba0087c93 Close typo in edited attributes 2022-10-14 08:10:39 -04:00
Jarrod Johnson c3afd45475 Normalize uid
python2 was crashing when getting unicode over the link.
2022-10-13 17:52:26 -04:00
Jarrod Johnson 730af73069 Correct open string in the attributes edit 2022-10-13 14:58:41 -04:00
Jarrod Johnson 84407e3d2b Correct syntax error in pxe handler 2022-10-13 14:49:09 -04:00
Jarrod Johnson a0702681da Merge remote-tracking branch 'lenovo/master' 2022-10-13 12:14:41 -04:00
Jarrod Johnson 88b741e026 Add 'firmwarenone' ip method
Add a seting to allow user to suppress all DHCP offer during
PXE/HTTP activity.  This enables configurations
where users want to externally manage filename explicitly in their own dhcp configuration.
2022-10-13 12:11:46 -04:00
Jarrod Johnson 4486fb5f81 Merge pull request #86 from erderial/patch-4
changed subprocess .run to Popen
2022-10-13 10:56:59 -04:00
Jarrod Johnson 8de7402b56 Add ability to get booturl redirect
In some environments, there's a desire to manually manage DHCP configuration.
In such a case, provide a url
that can be given to the dhcp server
to allow confluent to control the profile
without updating such a DHCP service.

With this change, a node can be told to boot:
http://confluentserver/confluent-api/booturl/by-node/n123/boot.ipxe

To be redirected to the currently applicable os profile.
2022-10-13 10:54:11 -04:00
erderial dc62fc3f51 changed subprocess .run to Popen
changed subprocess .run to Popen to open separate subprocesses for simultaneous run of console windows.
2022-10-12 22:35:05 +03:00
Jarrod Johnson 23ec46bb8b Add vlanid to the vmware deployment support 2022-10-12 13:08:57 -04:00
Jarrod Johnson 145be7ce31 Correct omission in private key access message during diskless boot 2022-10-07 16:47:48 -04:00
Jarrod Johnson d5d0852890 Tighten redfish check timeout
The default timeout is overkill in the nodediscover scenario.
Notably, we can receive replies from unreachable IP addresses,
and those will extend rescan to the full timeout.  The devices should
comfortably reply within 3 seconds, making scans exit in
a timely fashion.
2022-10-07 09:22:37 -04:00
Jarrod Johnson 4fed609050 Avoid enumerating members of a bond
Various parts of confluent that go to try to use
all the interfaces will now skip bond members.

One example problem is that joining the SSDP multicast
group for SSDP would cause the kernel to IGMPv6 out
on bond members as well as the bond itself.  This change
ensures that the bond interface is only used and never
bypassed.
2022-10-07 08:52:02 -04:00
Jarrod Johnson a77f211b8e Fix json restore of users and groups
Defaults were erroneously used
do to oversight and mistake in teh json restore code.
2022-10-06 09:23:43 -04:00
Jarrod Johnson 3c29a5aa7f Enable non-admin users for web gui 2022-10-06 08:49:00 -04:00
Jarrod Johnson 6eb4bf28e5 Another iteration to try to have IP adaptive syncfiles
It is likely that a client connects from fe80::, which
is explicitly omitted from ssh principals.

This time, have the client provide all currently set IP addresses
and the server will make a determination.

There remains the possibility it misconfigures a nic and tries to use that,
inducing failure.  One strategy would be to filter the addresses and
only provide from the 'current' interface.  Another is to just take
the hit as the node is likely going to suffer a lot from such a
misconfiguration anyway.
2022-10-05 12:23:47 -04:00
Jarrod Johnson 4cb222068f Sync up EL7 syncfileclient 2022-10-05 11:53:59 -04:00
Jarrod Johnson c612129d64 Have syncfiles attempt to use client ip, if feasible
When a node installs, it may not have it's node mapped address up,
or may not have one at all. Try to use the ip if it would be in the
same set that produced it's ssh certificate.

There remains a gap if a system has no static addressing *and* doesn't
map nodename to IP, but we have an impasse as the situation is too fuzzy
to grant a prinicpal in an SSH cert, and without that we can't securely
attempt rsync.  For now, this scenario would still fail and I will
just hope that doesn't come up.
2022-10-05 08:31:37 -04:00
Jarrod Johnson 13ba95bb99 Give up on waiting for disks
Some profiles may have all disk support suppressed through blacklist until %pre comes
along to fix it.  This avoids /dev/disk ever existing.

Wait up until 10 seconds before giving up. This gives disk subsystem a fair chance to
speed up and avoid a wait, with a fallback worst case of 10 seconds
2022-10-04 10:39:02 -04:00
Jarrod Johnson 75484db014 Fix macok incorrect value on finding the mac 2022-10-03 10:33:21 -04:00
Jarrod Johnson 0adfec0c44 Bump genesis version 2022-09-30 15:04:25 -04:00
Jarrod Johnson 4f67ed661d Remove curl from genesis
It is redundant with python function, and drags
sasl along as a significant dependency.
2022-09-30 15:02:54 -04:00
Jarrod Johnson 763b157802 Fix syntax error 2022-09-30 12:36:12 -04:00
Jarrod Johnson 6e803e9fca Add insecure protocol check 2022-09-30 12:22:39 -04:00
Jarrod Johnson 9ecd3e3ac7 Add API check
Particularly SELinux is a frequently missed configuration
facet, alert when the selinux is blocking.
2022-09-30 12:17:31 -04:00
Jarrod Johnson ee3aef0a4c Mark COPYRIGHT as legal in rpm 2022-09-30 11:02:55 -04:00
Jarrod Johnson b7dfe20286 Add legal artifacts to confluent_server 2022-09-30 10:43:18 -04:00
Jarrod Johnson 28f4571c8e Go for xCAT-neutral terminology 2022-09-29 16:09:46 -04:00
Jarrod Johnson c647dec069 Add message on successful node attribute run 2022-09-29 15:45:07 -04:00
Jarrod Johnson 903de26dd8 Add node attribute checks to selfcheck 2022-09-29 15:27:12 -04:00
Jarrod Johnson 76491785db Merge pull request #84 from erderial/patch-2
Adding wcons functionality for nodeconsole
2022-09-29 13:17:04 -04:00
Jarrod Johnson b7a424f4cc Merge pull request #85 from erderial/patch-3
Added -w flag for nodeconsole
2022-09-29 13:16:30 -04:00
erderial e180ec0bc8 removed null from the flow 2022-09-29 20:15:55 +03:00
Jarrod Johnson fcf342165c Fix apiclient detection of default interface
It was failing to record the default interface in its checks.
2022-09-29 13:15:37 -04:00
erderial d88207a468 Added -w flag for nodeconsole
Added -w flag for nodeconsole command, for xterm for now.
2022-09-29 19:24:57 +03:00
erderial e09c594ffb Adding wcons functionality for nodeconsole
Adding wcons functionality for nodeconsole for xterm first.
2022-09-29 18:58:06 +03:00
Jarrod Johnson cf000d6872 Add node name resolution check
A common scenario for closed networks
is a misconfigured DNS situation.

Detect and report, as this can wreak havoc on a confluent instance.
2022-09-29 09:57:43 -04:00
Jarrod Johnson 04ee7a8c31 Add '-l' to nodersync command 2022-09-29 08:05:02 -04:00
Jarrod Johnson 5a62307d1e Restore config by name
The change to allow CIDR syntax
broke for configurations that use name for
bmc 'address'.

Fix by letting getaddrinfo have a chance to process the ip before
trying to pton it.
2022-09-27 17:05:13 -04:00
Jarrod Johnson e5360b3b2f Have suse give up after a minute
If a network problem prevents the deployment nic from working,
give up eventually
2022-09-27 08:33:00 -04:00
Jarrod Johnson 484dbd9f74 Fix default interface detection 2022-09-23 16:10:55 -04:00
Jarrod Johnson 52626c56a8 Fix issues with the license restructure 2022-09-22 09:51:02 -04:00
Jarrod Johnson 885354f6b7 Rework license storage structure 2022-09-22 09:09:46 -04:00
Jarrod Johnson 0c08d8f6d3 Provide helpful error on bad user/password in delta pdu 2022-09-21 16:19:13 -04:00
Jarrod Johnson 25c66e163c Some notes on TPM recovery 2022-09-21 10:50:05 -04:00
Jarrod Johnson ba7832eb40 Fix restoring blocking on exit
When confetty/nodeconsole exits, correctly
clear NONBLOCK flag is an idempotent way.
2022-09-21 09:48:39 -04:00
Jarrod Johnson 440fcf2663 Further tweak el8 ident image support 2022-09-14 12:18:11 -04:00
Jarrod Johnson 0286b2e776 Further fixes to identity image in el8 2022-09-14 11:57:02 -04:00
Jarrod Johnson aa2a8e2d5a Adjust ported coreos ident image support to el8 install environment 2022-09-14 11:18:01 -04:00
Jarrod Johnson 65e97073e2 Add identity image support to EL8 scripted install profiles 2022-09-14 11:00:04 -04:00
Jarrod Johnson 5a935d99fc Have SMM devices register cleanly
In remote discovery registration, the
SMM path was not fully implemented
2022-09-13 13:29:42 -04:00
Jarrod Johnson 785d7d40fa Add COPYRIGHT notice 2022-09-09 12:50:38 -04:00
Jarrod Johnson 91f4ef9747 Attempt to fill in more missing metadata 2022-09-09 12:26:38 -04:00
Jarrod Johnson 9025918609 Fix missing information in packaging metadata 2022-09-09 12:10:32 -04:00
Jarrod Johnson 7cbd105ae3 Workaround TSM issue with redfish configuration 2022-09-09 12:04:38 -04:00
Jarrod Johnson 2bc2736da4 Fix neighutil invocation of ipn_is_local 2022-09-08 16:07:04 -04:00
Jarrod Johnson 4a8af0ad85 Fix assumptions about ip going into netutil 2022-09-08 14:35:16 -04:00
Jarrod Johnson 7b98b7dc00 Fix wrong uid after duplicate identity check 2022-09-08 09:51:21 -04:00
Jarrod Johnson cde18bcd3a Cap the number of deferred packets
Prevent deferred packets from growing endlessly
if activity is keeping the loop running.
2022-09-07 08:04:47 -04:00
Jarrod Johnson 60cfa1d3c5 Skip peer probe on remote
When remote ip is detected,
communicate by returning False
instead of None.

Use this indication to let ssdp
skip a transmit and growing
pending list in such a case.
2022-09-06 16:40:34 -04:00
Jarrod Johnson 596fcb0f4c Implement mitigations for ovewhelming SSDP
First, for a given contiguous set of snoop activity, start ignoring a given peer during that contiguous chenk after it has been considered once.

Further, make get_hwaddr cheaper for attempts against
remote IPs.

To facilitate the above, create an efficient 'ip_is_local' to be
a relatively cheap function, with
potential to cache result in future
if it needs to be even cheaper.
2022-09-06 16:08:31 -04:00
Jarrod Johnson 7980534bad Fix confluentdbgcli.py for python3 2022-09-02 15:11:30 -04:00
Jarrod Johnson 6c1f87aeb7 Add mechanism for copernicus to request any confluent
This can be used for network debug in a generic way, to identify vlan adjacency without regard to nodedoploy state or uuid matching.
2022-09-02 13:32:05 -04:00
Jarrod Johnson 1c811dbf3e Fix python path automatically in confluent_selfcheck 2022-09-02 10:11:12 -04:00
Jarrod Johnson 503746131c Add selfcheck to packaging 2022-09-02 09:53:06 -04:00
Jarrod Johnson a0037a305c Add confluent_selfcheck to server package 2022-09-02 09:44:13 -04:00
Jarrod Johnson d1d15f29c1 Add facility to fix confluent uuid problem 2022-09-01 13:26:25 -04:00
Jarrod Johnson b98759698a Sync up getinstalldisk and add another m.2 model 2022-09-01 13:22:50 -04:00
Jarrod Johnson 20992b2d17 Add check for actual file download 2022-09-01 13:21:39 -04:00
Jarrod Johnson 67f0c8a81b Add IPv6 and insecure boot checking 2022-09-01 13:17:17 -04:00
Jarrod Johnson 28331adced Add TFTP and ssh key checks to checkconfluent 2022-08-31 17:30:41 -04:00
Jarrod Johnson ed91e0f2f3 Have askpass delete itself
This causes ssh-add to give up, instead of endlessly rerunning
the askpass script.
2022-08-31 17:17:33 -04:00
Jarrod Johnson 99a5c454ba Begin work on a sanity checker
Check various facets that are frequently not quite right, making
recommendations on how to correct.
2022-08-30 16:59:40 -04:00
Jarrod Johnson 908e51221c Correct minor formatting mistake in warning 2022-08-29 12:22:14 -04:00
Jarrod Johnson 8277701af6 Rewrite site ssh even if
the /etc copy already exists.

IT may be that /var/lib/confluent is being repaired, in which
case just copy existng over while giving warning.
2022-08-29 12:16:35 -04:00
Jarrod Johnson 570611f22b Have osdeploy initialize skip SSH regen
When generating new key materials, most people say 'yes' and cause problems
where they cycle valid keys without
realizing the significance.

Replace prompting with an emphasized warning instead.
2022-08-29 11:10:45 -04:00
Jarrod Johnson 2a3e6cd6f1 Change websocket dependency name in EL7 2022-08-26 08:16:22 -04:00
Jarrod Johnson 4e44188253 Ensure early existance of ca.pem
Prior to install, enable apiclient
to have the ca.pem where it would
expect it to be.
2022-08-25 16:45:00 -04:00
Jarrod Johnson 352da94005 Implement rebase feature ofr osdeploy
Permit user to opt into a rebase of a
profile, to pick up potential updates
from the confluent packaged stock
profiles for files the user has not yet
customized.
2022-08-25 15:21:49 -04:00
Jarrod Johnson e774add916 Set timezone on diskless boots by default
During onboot, use confluent directed timezone
info to set the timezone if the
disk image is incorrect.
2022-08-24 16:09:05 -04:00
Jarrod Johnson d72bac5faf Add more to the SUSE profiles
Add exetensibility to pre and sample directories
2022-08-24 16:07:38 -04:00
Jarrod Johnson 93b7547c58 Enable IPMI for user if IPMI has been enabled globally elsewhere
Scenarios have come up with trying to repair partially
configured configuration, break
the global and per-account check
into separate concerns.
2022-08-24 10:13:53 -04:00
Jarrod Johnson 31b3d6ea06 Move manifest data into dedicated file 2022-08-24 09:29:48 -04:00
Jarrod Johnson 42b4944542 Fix build script for vtbufferd
Update for new licensing standard.
2022-08-23 16:08:25 -04:00
Jarrod Johnson 04526ae8cc Update license to NOTICE file
Bundled third party license content is now described under NOTICE file.
2022-08-23 15:52:50 -04:00
Jarrod Johnson d97c508d86 Add hash manifest of new os profiles
When importing an image and taking stock copy, mark the files to allow detection of stock
versus customized profile content.

This will be used by a rebase command to know when
to overwrite or when to leave a file alone.
2022-08-23 15:25:17 -04:00
Jarrod Johnson 801e43936c Revise ESXi routed deployment
-Have apiclient set timeout on getting credential to avoid hang
-Change dcuiweasel to start shell earlier for better debug
-Do not expire the ident token if deployment is armed continuous anyway
2022-08-19 16:06:46 -04:00
Jarrod Johnson a445107c7f Fix setting privilege level alone for ipmi
The logic incorrectly had it depend on password also being present.
2022-08-19 09:10:52 -04:00
Jarrod Johnson dde66c53c9 Dynamically ascertain name scheme for Delta pdu
Some delta pdus have different name schemes
than others, take the hit of
awkward parsing to autodetect.
2022-08-17 10:20:26 -04:00
Jarrod Johnson 57fcc8a243 Start SSH agent even on older ssh
The unusual path to automation key for syncfiles and ansbile
is most easily handled by ssh-agent, even if no passphrase
will be used
2022-08-16 15:06:26 -04:00
Jarrod Johnson 41c3c4fb5f Handle metapackages
If a metapackage gets pulled in
as related, do not let it mess up
the license list.
2022-08-11 14:09:55 -04:00
Jarrod Johnson 7b3c1e5405 Capture license content from related packages
Some files that get gathered into genesis
have their license in a related rpm, but that related rpm does not otherwise get captured.

So pull all correlated license material
in the license capture process.
2022-08-11 13:42:36 -04:00
Jarrod Johnson 047cd6302a Add wait for IP connectivity
After config, there may be a delay
before the configuration takes effect.

This delay can break nodeconfig.

Try to wait for the delay to pass.
2022-08-09 08:50:19 -04:00
Jarrod Johnson f0c8eee956 Add facility to auto-exec nodeconfig on discovery
This permits more open ended node configuration when discovery happens.
2022-08-08 16:13:01 -04:00
Jarrod Johnson 1125e4c712 Advance concetpual debian support 2022-08-08 14:23:01 -04:00
Jarrod Johnson 2aed973a8b Have apiclient check all hosts for connectivity
Further allow it to output the result and feed that to esxi startup.
2022-08-08 11:18:35 -04:00
Jarrod Johnson 078e755ec7 Actually feed preseed into config
It must be done to the live cdebconf state *and* preseed.cfg,
since one is referenced immediately and then discarded when
preseed read in.
2022-08-05 16:05:26 -04:00
Jarrod Johnson e3ed54ebf3 Advance the bootstrap of debian installation concept 2022-08-05 14:05:27 -04:00
Jarrod Johnson 9cac0c1705 Amendments to confluent initialization 2022-08-04 16:51:33 -04:00
Jarrod Johnson 2fe852f122 Add draft of a debian-installer-startup script
This is a draft for use in debian profiles to get started
2022-08-04 16:27:58 -04:00
Jarrod Johnson 258c4970c0 Change makeksnet from yaml to json
Older vmware did just json, which is fine, just have to use
the json file that was there just in case something like this
came up.
2022-08-04 10:39:10 -04:00
Jarrod Johnson 610e7bf044 Constrain ip-less offers
PXE and HTTP client define a behavior for using non-address portion of an offer if the
offer has none. However, other clients, like
udhcpc will be confounded by such offers.

Ensure that client specifically sets VCI to indicate
it understand such an offer before replying.

This as yet generally doesn't matter as UUID is not sent by OS installers, however
some OSes can't do do API calls over LLA, and
thus we want to start allowing OS requests with
UUID and only offer when it makes sense.
2022-07-29 12:49:25 -04:00
Jarrod Johnson 6b95bc7932 Fix key name 2022-07-27 12:08:58 -04:00
Jarrod Johnson 35701cdf01 Allow ident net config to override deploycfg
In routed deployment, deploycfg will
be missing network info, use
the ident provided network if detected.
2022-07-27 11:41:29 -04:00
Jarrod Johnson c1ad4357dc Fix for loop variable name 2022-07-27 08:37:09 -04:00
Jarrod Johnson 9987cb5c03 Advance state of routed esxi deployment 2022-07-27 07:51:41 -04:00
Jarrod Johnson e8d2f550b8 Draft work on ESXi identity image deployment
Prepare for routed deployment of ESXi
2022-07-25 17:05:30 -04:00
Jarrod Johnson 9fe156601b Add netmask to net config data
Some clients may want to consume netmask
without going to the trouble of converting,
so provide the extra data a different way.
2022-07-25 15:54:07 -04:00
Jarrod Johnson 830c9e171f Add IP detection on local segment from remote registration
If an ip address is missing, but linklocal is set, try to search the
local nics for a viable connection to use.
2022-07-22 17:17:35 -04:00
Jarrod Johnson 0ac2bce883 Have XCC use a null string for ipaddr
This avoids the remote discovery failure for now.
2022-07-22 13:31:11 -04:00
Jarrod Johnson 6f619bc896 Change ipaddr to a property for allowing logic 2022-07-22 13:23:47 -04:00
Jarrod Johnson bdd5dddce0 Fix typo in log message 2022-07-21 11:20:31 -04:00
Jarrod Johnson d61dcee4fa Fix handling of explicit prefix
Switch to just ip in time and return prefix
length as int.
2022-07-21 11:06:01 -04:00
Jarrod Johnson d385ad1a0a Support explicit prefix in xcc discovery 2022-07-21 10:13:00 -04:00
Jarrod Johnson ef2c7b5bbc Fix errant reference 2022-07-21 09:57:29 -04:00
Jarrod Johnson 2256b341b9 Tolerate '/' in hardwaremanagement.manager
This paves the way to allowing CIDR syntax to
indicate prefix length for remote XCCs
2022-07-21 09:54:00 -04:00
Jarrod Johnson 79421a724f Fix base64 decode of fingerprint
base64 was being done against wrong variable
2022-07-21 08:33:12 -04:00
Jarrod Johnson 7751a71851 Merge branch 'remote_discovery' 2022-07-20 16:22:01 -04:00
Jarrod Johnson 2d8bcb4c0f Incorporate auto discovery for remote discovery
Avail ourselves of secure vouching to handle new and
replaced.
2022-07-20 16:21:25 -04:00
Jarrod Johnson 0dc7b532cc Implement registration and retrieval
Remote discovery can now be registered by
switches.
2022-07-20 13:01:11 -04:00
Jarrod Johnson 97c520db10 Make error message more clear 2022-07-19 10:16:48 -04:00
Jarrod Johnson 480849640e Make error message more clear 2022-07-19 10:16:18 -04:00
Jarrod Johnson 42055e2648 Merge branch 'master' into remote_discovery 2022-07-18 15:52:42 -04:00
Jarrod Johnson 789def17d1 Do not tail old content from firstboot
Tail only new content being fleshly logged
2022-07-18 09:35:40 -04:00
Jarrod Johnson 926f9e2cdd Enable more plugins for collective routing 2022-07-13 08:58:31 -04:00
Jarrod Johnson c627ac73ee Make a specific error on nodesupport 2022-07-11 16:18:33 -04:00
Jarrod Johnson 2058d1fba8 Add ESXi 8 support
ESXi changes security policies, adapt
to navigate both old and new sorts of rules
2022-07-08 13:36:21 -04:00
Jarrod Johnson beb4c66b65 Fix spelling in error message 2022-07-08 10:50:45 -04:00
Jarrod Johnson f467cfe7c4 Add log message for mac interrogation of switch
Clarify when things go wrong due to certificate.
2022-06-30 13:28:26 -04:00
Jarrod Johnson 3bd11da807 Remove extraneous line from setupssh.sh 2022-06-30 13:27:39 -04:00
Jarrod Johnson eaffac0433 Allow blanking a value to default a plugin attribute 2022-06-30 13:27:25 -04:00
Jarrod Johnson 500e083746 Enable ipmi user if required
If redfish models ipmi as an account type, and user wants ipmi, add it to the account.
2022-06-28 14:25:12 -04:00
Jarrod Johnson 29965f6ec9 Add a catch all to redfish for xcc
Newer xcc changes things yet again, but
we are comfortably in the firmware that can be bootstrapped
with redfish, so use that instead once we've cleared the
redfish incapable variants.
2022-06-28 14:24:48 -04:00
Jarrod Johnson f65ff1268a Add new state offline to confluent storage states 2022-06-28 12:15:54 -04:00
Jarrod Johnson a54a9a5d09 Enable ipmi user if required
If redfish models ipmi as an account type, and user wants ipmi, add it to the account.
2022-06-27 14:34:37 -04:00
Jarrod Johnson 9b79da9522 Add a catch all to redfish for xcc
Newer xcc changes things yet again, but
we are comfortably in the firmware that can be bootstrapped
with redfish, so use that instead once we've cleared the
redfish incapable variants.
2022-06-27 14:12:51 -04:00
Jarrod Johnson 04c2b1a322 Provide an authenticated path for discovery registration 2022-06-22 16:47:40 -04:00
Jarrod Johnson 559a7ca7b8 Merge branch 'master' into remote_discovery 2022-06-21 14:56:56 -04:00
Jarrod Johnson 0a10311fea Add more verbose ssh connection feedback
Make the nature of connecting more explicit and errors
more reliably holding the session up and asking for relog
2022-06-17 15:35:06 -04:00
Jarrod Johnson 715bcb2f50 Prevent shell session from playing console output 2022-06-17 14:54:41 -04:00
Jarrod Johnson 8d5ad0d4a6 Fix EL7 spec file syntax 2022-06-17 13:11:08 -04:00
Jarrod Johnson 1387a67b61 Correct spec syntax error 2022-06-17 12:37:20 -04:00
Jarrod Johnson 4b08273379 Move EL7 back to python2
EL7's python3 support is barren and would require a lot of dependency
work.

Move EL7 back to python2 and will deprecate EL7 support when we ditch
python2
2022-06-17 12:10:44 -04:00
Jarrod Johnson e0c3232180 Fix syntax error in el7 prescript 2022-06-17 09:30:26 -04:00
Jarrod Johnson bd95f00680 Fix EL7 typeo in postscript 2022-06-17 09:08:12 -04:00
Jarrod Johnson bfecaa389d Adjust to correct ntp for 9 and up 2022-06-17 09:06:33 -04:00
Jarrod Johnson 7aca7a19f9 Install apiclient in a normal location for EL7 2022-06-15 16:42:50 -04:00
Jarrod Johnson c400671ad7 Add old profile compatible apiclient location 2022-06-15 16:39:55 -04:00
Jarrod Johnson c96955b369 Add catch-all packaging for EL7
EL7 now precompiles and flags it in the packaging
2022-06-15 16:34:57 -04:00
Jarrod Johnson 2bb519c158 Fix EL7 deployment compatibility 2022-06-15 16:10:57 -04:00
Jarrod Johnson e5c33cacd5 Change SuSE rpm name to pyyaml 2022-06-15 15:11:07 -04:00
Jarrod Johnson 03f0f16ed8 Change to dnspython for suse 2022-06-15 15:06:52 -04:00
Jarrod Johnson 0f815dc7d3 Switch to python3 for all builds 2022-06-15 15:00:19 -04:00
Jarrod Johnson dbdc99905d Update confluent server to python3 dependencies only 2022-06-15 14:31:32 -04:00
Jarrod Johnson 2d665fb816 Merge branch 'py2to3' 2022-06-15 12:42:04 -04:00
Jarrod Johnson 26e0fa8c91 Add swraid example to misc 2022-06-15 09:50:06 -04:00
Jarrod Johnson 83da1359df Add a sample vroc 'pre' script for reference 2022-06-15 08:40:23 -04:00
Jarrod Johnson 0f1581f8f7 Add a sample script to fetch user/pass info from confluent db 2022-06-10 14:18:35 -04:00
Jarrod Johnson 13d4d1dd98 Ensure that python3 will execute before doing migrate
If python3 is not the executable name, prevent the restoration
attempt from happening.
2022-06-10 11:19:21 -04:00
Jarrod Johnson db5c31030d Migrate DB on start
If python2 db format detected, use python2 to
dump to text, then python3 to restore to
get the python3 native version
2022-06-09 16:23:35 -04:00
Jarrod Johnson 6f484aab53 Allow restore to replace unsupported format
Going from python 2 to python 3, the dbm format
goes from the default to unsupported.

This allows a python3 confluentdbutil restore to handle
a python2 dump of unsupported format.
2022-06-09 15:49:06 -04:00
Jarrod Johnson 44cf56857e Add fallbacks to PyCrypto compatible names
Cryptodome is not always packaged with the
explicit form, fall back to the Crypto names
hoping that the user wouldn't be trying to use
PyCrypto is this day and age.
2022-06-09 10:48:12 -04:00
Jarrod Johnson 17e223e21c Suppress stray fakecmdline output 2022-06-09 09:15:56 -04:00
Jarrod Johnson 5ee6d0ca5d Fix ordering of arguments
The -text was between startdate and its argument
2022-06-09 08:30:03 -04:00
Jarrod Johnson 2825af19c4 Do not clutter the pem file with text 2022-06-09 08:04:15 -04:00
Jarrod Johnson e9ac43f49e Add autocons to bootloader config
In newer suse, the fake cmdline trick is fouled, so carry into
autoyast file
2022-06-09 07:55:42 -04:00
Jarrod Johnson 5ee0572f54 Change to using 'full' openssl ca
OpenSSL does not allow access to custom start
date without the full 'ca' facility, do the
work to set up the full CA and then
backdate certificates.

This does open the way for managed CA if required.
2022-06-08 17:10:11 -04:00
Jarrod Johnson 3da67db806 Fix early bailout of nodeconfig
Do not have nodeconfig bail out on first sign of trouble, attempt to continue.
2022-06-08 13:43:25 -04:00
Jarrod Johnson 826c9eedb0 Document -l in nodeconsole man page 2022-06-08 11:14:51 -04:00
Jarrod Johnson af19e98ce8 Remove use of eventlet in client side
The client side does not use eventlet, so allow
fallback to the normal socket and select
to keep the client module whole in the
face of that missing.
2022-06-08 11:03:56 -04:00
Jarrod Johnson 0dcd1442c9 Avoid nodeshell/noderun getting stuck on stdin
Some applications will tend to hang on stdin if
stdin is readable. Provide /dev/null to suppress that behavior.
2022-06-08 10:21:08 -04:00
Jarrod Johnson 2f904d10e9 Fix identity yaml parsing
Switch to sed rather than trying to use head.  There may or
may not be a second match, so need sed logic to understand
whether it's a match or not to keep or throw out.
2022-06-08 09:23:56 -04:00
Jarrod Johnson fdaecf2cbc Relay input errors to caller in dispatch 2022-06-07 13:36:31 -04:00
Jarrod Johnson 8bb565e938 Implement error on invalid attribute filter
This will cause noderange to probably error out.

Note that invalid attribute names starting with net, power, or custom are treated as always valid.
2022-06-07 11:45:06 -04:00
Jarrod Johnson 0b20e0b634 Fix confuent scan for python 3.9
Python 3.9 removes the scope from the string
address, put it back if missing since it's required
to actually be usable.
2022-06-07 10:55:56 -04:00
Jarrod Johnson b32c343a0c Switch to importlib for newer python
imp is deprecated, despite being much simpler,
so use importlib in python3.6+ distributions.
2022-06-07 10:35:08 -04:00
Jarrod Johnson 942121d73a Remove unavaiable clear from el9 diskless 2022-06-07 09:48:52 -04:00
Jarrod Johnson 55f42bc909 Add el9 imgutil 2022-06-07 09:06:59 -04:00
Jarrod Johnson 84037420d1 Add el9 tree for diskless 2022-06-06 13:18:37 -04:00
Jarrod Johnson e7bea0df45 Advance work on EL9 diskless support 2022-06-06 13:10:22 -04:00
Jarrod Johnson 94955dd091 Bring down track number
Use 2 heads with 4 sectors per track to get the track number down for
reasonable images.

Newer mtools forbids large track numbers.
2022-06-06 11:57:19 -04:00
Jarrod Johnson 739890471d Support newer python that removes fromstring
Python 3.9 does not understand the fromstring function anymore.
2022-06-06 11:37:39 -04:00
Jarrod Johnson 0baa2eecab Break out on deployment failure 2022-06-06 11:05:22 -04:00
Jarrod Johnson 46fec89460 Fix routed deployment api key usage 2022-06-06 10:15:54 -04:00
Jarrod Johnson 997bd3ac34 Implement outlet control for Eaton PDU 2022-06-03 17:06:37 -04:00
Jarrod Johnson 799050fea2 In-progress Eaton PDU support 2022-06-03 16:26:07 -04:00
Jarrod Johnson 80186f2c77 Add a delta pdu plugin
This has received limited testing, and the PDUs cannot be used with secure protocols
2022-06-03 10:24:44 -04:00
Jarrod Johnson 64b8893b80 Add a delta pdu plugin
This has received limited testing, and the PDUs cannot be used with secure protocols
2022-06-03 10:24:25 -04:00
Jarrod Johnson ae4b5c5100 Amend nodeping behavior and documentation 2022-06-02 16:04:19 -04:00
Jarrod Johnson f13df801fd Merge branch 'master' into remote_discovery 2022-05-31 13:53:47 -04:00
Jarrod Johnson 83acdab216 Amend python 3.9 compatibility fix
Avoid checking None for is_alive or isAlive
2022-05-31 11:23:27 -04:00
Jarrod Johnson b42dafb085 Fix python 3.9 compatibility
In python 3.9, the % is no longer included
in the first member of the address tuple.

Handle both scenarios by adding '%' in for versions
that seem to want to remove it.
2022-05-31 11:01:09 -04:00
Jarrod Johnson b5f5ba69d2 Fix python 3.9 compatibility
Python 3.9 renamed an attribute on a threading object, try
both names to support old and new python
2022-05-31 10:18:42 -04:00
Jarrod Johnson 6d07dac46c Fix ipmi missing logging state and trim el9 dependencies 2022-05-27 16:10:08 -04:00
Jarrod Johnson e4e859c798 Fix invocation of monotonic_time 2022-05-26 18:07:19 -04:00
Jarrod Johnson ff698ea06b Merge branch 'webauthn' 2022-05-26 17:42:15 -04:00
Jarrod Johnson 9c7e23f29e Add missing nodepower statuses 2022-05-26 17:41:54 -04:00
Jarrod Johnson b638bb69f9 Change webauthn to use confluent user db
This allows persistence with the rest of the
configuration.
2022-05-26 17:41:16 -04:00
Jarrod Johnson 7072a85d79 Transition to multi-authenticator support
Provide a way to store a plurality of keys for a user.
This enables use of 'backup' authenticators.
2022-05-26 16:34:18 -04:00
Jarrod Johnson 9b6114f523 Break if stuck in loop for over a minute 2022-05-26 15:01:47 -04:00
Jarrod Johnson 4773acb37d Adapt geist to work with python2 2022-05-25 10:58:35 -04:00
Jarrod Johnson ee1a763c68 Add el7 to alternat squashfs name 2022-05-09 09:57:35 -04:00
Jarrod Johnson f138b4513c Merge branch 'master' into remote_discovery 2022-05-09 08:33:24 -04:00
Jarrod Johnson d8a2671dd6 Fix directory traversal 2022-04-25 13:11:43 -04:00
Jarrod Johnson 14efec3603 Add file to show the rpm versions at build time of genesis 2022-04-25 13:04:45 -04:00
Jarrod Johnson 00589d06f5 Refactor relay and add to XCC/SMM
Extract relay versus direct determination and
inject into XCC and SMM handlers
2022-04-21 09:40:09 -04:00
Jarrod Johnson 334ce65919 Add facility for forwarding agent
Remote discovery will require that the reporting agent
provides port forwarding facility for https access, to
allow access without route to the managing confluent server.

This will allow the info reported to indicate use of this
forwarding facility and the base handler adds ability to
generically get the certificate.
2022-04-20 17:11:01 -04:00
472 changed files with 30601 additions and 2727 deletions
+30
View File
@@ -0,0 +1,30 @@
# Confluent
![Python 3](https://img.shields.io/badge/python-3-blue.svg) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/xcat2/confluent/blob/master/LICENSE)
Confluent is a software package to handle essential bootstrap and operation of scale-out server configurations.
It supports stateful and stateless deployments for various operating systems.
Check [this page](https://hpc.lenovo.com/users/documentation/whatisconfluent.html
) for a more detailed list of features.
Confluent is the modern successor of [xCAT](https://github.com/xcat2/xcat-core).
If you're coming from xCAT, check out [this comparison](https://hpc.lenovo.com/users/documentation/confluentvxcat.html).
# Documentation
Confluent documentation is hosted on: https://xcat2.github.io/confluent-docs/
# Download
Get the latest version from: https://hpc.lenovo.com/users/downloads/
Check release notes on: https://hpc.lenovo.com/users/news/
# Open Source License
Confluent is made available under the Apache 2.0 license: https://opensource.org/license/apache-2-0
# Developers
Want to help? Submit a [Pull Request](https://github.com/xcat2/confluent/pulls).
+8
View File
@@ -0,0 +1,8 @@
FROM almalinux:10
RUN ["yum", "-y","update"]
RUN ["yum", "-y","install","gcc","make","rpm-build","python3-devel","python3-setuptools","createrepo","python3", "perl", "perl-DBI", "perl-JSON", "perl-XML-LibXML", "pinentry-tty", "rpm-sign", "git", "golang"]
ADD rpmmacro /root/.rpmmacros
ADD buildpackages.sh /bin/
#VOLUME ["/rpms", "/srpms"]
CMD ["/bin/bash","/bin/buildpackages.sh"]
+6
View File
@@ -0,0 +1,6 @@
for package in /srpms/*; do
rpmbuild --rebuild $package
done
find ~/rpmbuild/RPMS -type f -exec cp {} /rpms/ \;
+3
View File
@@ -0,0 +1,3 @@
%_gpg_digest_algo sha256
%_gpg_name Lenovo Scalable Infrastructure
+8
View File
@@ -0,0 +1,8 @@
FROM almalinux:8
RUN ["yum", "-y","update"]
RUN ["yum", "-y","install","gcc","make","rpm-build","python3-devel","python3-setuptools","createrepo","python3", "perl", "perl-DBI", "perl-JSON", "perl-Net-DNS", "perl-DB_File", "perl-XML-LibXML", "rpm-sign", "git", "fuse-devel","libcurl-devel"]
ADD rpmmacro /root/.rpmmacros
ADD buildpackages.sh /bin/
#VOLUME ["/rpms", "/srpms"]
CMD ["/bin/bash","/bin/buildpackages.sh"]
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
for package in /srpms/*; do
rpmbuild --rebuild $package
done
find ~/rpmbuild/RPMS -type f -exec cp {} /rpms/ \;
+2
View File
@@ -0,0 +1,2 @@
%_gpg_digest_algo sha256
%_gpg_name Lenovo Scalable Infrastructure
+10
View File
@@ -0,0 +1,10 @@
FROM almalinux:9
RUN ["yum", "-y","update"]
RUN ["yum", "-y","install","gcc","make","rpm-build","python3-devel","python3-setuptools","createrepo","python3", "perl", "perl-DBI", "perl-JSON", "perl-Net-DNS", "perl-DB_File", "perl-XML-LibXML", "pinentry-tty", "rpm-sign", "epel-release", "git"]
RUN ["crb", "enable"]
RUN ["yum", "-y","install","fuse-devel","libcurl-devel"]
ADD rpmmacro /root/.rpmmacros
ADD buildpackages.sh /bin/
#VOLUME ["/rpms", "/srpms"]
CMD ["/bin/bash","/bin/buildpackages.sh"]
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
for package in /srpms/*; do
rpmbuild --rebuild $package
done
find ~/rpmbuild/RPMS -type f -exec cp {} /rpms/ \;
+2
View File
@@ -0,0 +1,2 @@
%_gpg_digest_algo sha256
%_gpg_name Lenovo Scalable Infrastructure
+12
View File
@@ -0,0 +1,12 @@
FROM ubuntu:noble
ADD stdeb.patch /tmp/
ADD buildapt.sh /bin/
ADD distributions.tmpl /bin/
RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y", "reprepro", "python3-stdeb", "gnupg-agent", "devscripts", "debhelper", "libsoap-lite-perl", "libdbi-perl", "quilt", "git", "python3-pyparsing", "python3-dnspython", "python3-eventlet", "python3-netifaces", "python3-paramiko", "dh-python", "libjson-perl", "ronn", "alien", "gcc", "make"]
RUN ["mkdir", "-p", "/sources/git/"]
RUN ["mkdir", "-p", "/debs/"]
RUN ["mkdir", "-p", "/apt/"]
RUN ["bash", "-c", "patch -p1 < /tmp/stdeb.patch"]
CMD ["/bin/bash", "/bin/buildapt.sh"]
+21
View File
@@ -0,0 +1,21 @@
#cp -a /sources/git /tmp
for builder in $(find /sources/git -name builddeb); do
cd $(dirname $builder)
./builddeb /debs/
done
cp /prebuilt/* /debs/
cp /osd/*.deb /debs/
mkdir -p /apt/conf/
CODENAME=$(grep VERSION_CODENAME= /etc/os-release | sed -e 's/.*=//')
if [ -z "$CODENAME" ]; then
CODENAME=$(grep VERSION= /etc/os-release | sed -e 's/.*(//' -e 's/).*//')
fi
if ! grep $CODENAME /apt/conf/distributions; then
sed -e s/#CODENAME#/$CODENAME/ /bin/distributions.tmpl >> /apt/conf/distributions
fi
cd /apt/
reprepro includedeb $CODENAME /debs/*.deb
for dsc in /debs/*.dsc; do
reprepro includedsc $CODENAME $dsc
done
+7
View File
@@ -0,0 +1,7 @@
Origin: Lenovo HPC Packages
Label: Lenovo HPC Packages
Codename: #CODENAME#
Architectures: amd64 source
Components: main
Description: Lenovo HPC Packages
+34
View File
@@ -0,0 +1,34 @@
diff -urN t/usr/lib/python3/dist-packages/stdeb/cli_runner.py t.patch/usr/lib/python3/dist-packages/stdeb/cli_runner.py
--- t/usr/lib/python3/dist-packages/stdeb/cli_runner.py 2024-06-11 18:30:13.930328999 +0000
+++ t.patch/usr/lib/python3/dist-packages/stdeb/cli_runner.py 2024-06-11 18:32:05.392731405 +0000
@@ -8,7 +8,7 @@
from ConfigParser import SafeConfigParser # noqa: F401
except ImportError:
# python 3.x
- from configparser import SafeConfigParser # noqa: F401
+ from configparser import ConfigParser # noqa: F401
from distutils.util import strtobool
from distutils.fancy_getopt import FancyGetopt, translate_longopt
from stdeb.util import stdeb_cmdline_opts, stdeb_cmd_bool_opts
diff -urN t/usr/lib/python3/dist-packages/stdeb/util.py t.patch/usr/lib/python3/dist-packages/stdeb/util.py
--- t/usr/lib/python3/dist-packages/stdeb/util.py 2024-06-11 18:32:53.864776149 +0000
+++ t.patch/usr/lib/python3/dist-packages/stdeb/util.py 2024-06-11 18:33:02.063952870 +0000
@@ -730,7 +730,7 @@
example.
"""
- cfg = ConfigParser.SafeConfigParser()
+ cfg = ConfigParser.ConfigParser()
cfg.read(cfg_files)
if cfg.has_section(module_name):
section_items = cfg.items(module_name)
@@ -801,7 +801,7 @@
if len(cfg_files):
check_cfg_files(cfg_files, module_name)
- cfg = ConfigParser.SafeConfigParser(cfg_defaults)
+ cfg = ConfigParser.ConfigParser(cfg_defaults)
for cfg_file in cfg_files:
with codecs.open(cfg_file, mode='r', encoding='utf-8') as fd:
cfg.readfp(fd)
+9
View File
@@ -0,0 +1,9 @@
cd ~/confluent
git pull
rm ~/rpmbuild/RPMS/noarch/*osdeploy*
rm ~/rpmbuild/SRPMS/*osdeploy*
sh confluent_osdeploy/buildrpm-aarch64
mkdir -p $HOME/el9/
mkdir -p $HOME/el10/
podman run --rm -it -v $HOME:/build el9build bash /build/confluent/confluent_vtbufferd/buildrpm /build/el9/
+77
View File
@@ -0,0 +1,77 @@
Project: https://hpc.lenovo.com/users/
Source: https://github.com/lenovo/confluent
Upstream-Name: confluent-client
All file of the Confluent-client software is distributed under the terms of an Apache-2.0 license as indicated below:
Files: *
Copyright: 2014-2019 Lenovo
License: Apache-2.0
File: client.py:
Copyright: 2014 IBM Corporation
2015-2019 Lenovo
License: Apache-2.0
File: sortutil.py,
tlvdata.py
Copyright: 2014 IBM Corporation
2015-2016 Lenovo
License: Apache-2.0
File: tlv.py
Copyright: 2014 IBM Corporation
License: Apache-2.0
License: Apache-2.0
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
+11 -6
View File
@@ -14,11 +14,16 @@ import shutil
shutil.copyfile('doc/man/nodeattrib.ronn.tmpl', 'doc/man/nodeattrib.ronn')
shutil.copyfile('doc/man/nodegroupattrib.ronn.tmpl', 'doc/man/nodegroupattrib.ronn')
with open('doc/man/nodeattrib.ronn', 'a') as outf:
for field in sorted(attr.node):
outf.write('\n* `{0}`:\n {1}\n'.format(field, attr.node[field]['description']))
with open('doc/man/nodegroupattrib.ronn', 'a') as outf:
for field in sorted(attr.node):
outf.write('\n* `{0}`:\n {1}\n'.format(field, attr.node[field]['description']))
def append_attributes(filename):
with open(filename, 'a') as outf:
for field in sorted(attr.node):
outf.write('\n* `{0}`:\n {1}\n'.format(field, attr.node[field]['description']))
# Optionally write valid values if they exist
for key, values in attr.node[field].items():
if key.startswith('valid'):
values_formatted = ', '.join("'{0}'".format(v) for v in values)
outf.write(f'\n Valid values: {values_formatted}\n')
append_attributes('doc/man/nodeattrib.ronn')
append_attributes('doc/man/nodegroupattrib.ronn')
+9 -2
View File
@@ -21,6 +21,7 @@
import optparse
import os
import re
import select
import sys
@@ -84,6 +85,7 @@ fullline = sys.stdin.readline()
printpending = True
clearpending = False
holdoff = 0
padded = None
while fullline:
for line in fullline.split('\n'):
if not line:
@@ -92,13 +94,18 @@ while fullline:
line = 'UNKNOWN: ' + line
if options.log:
node, output = line.split(':', 1)
output = output.lstrip()
if padded is None:
if output.startswith(' '):
padded = True
else:
padded = False
if padded:
output = re.sub(r'^ ', '', output)
currlog = options.log.format(node=node, nodename=node)
with open(currlog, mode='a') as log:
log.write(output + '\n')
continue
node, output = line.split(':', 1)
output = output.lstrip()
grouped.add_line(node, output)
if options.watch:
if not holdoff:
+234 -16
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 IBM Corporation
@@ -45,6 +45,7 @@ import math
import getpass
import optparse
import os
import re
import select
import shlex
import signal
@@ -132,6 +133,8 @@ def print_help():
def updatestatus(stateinfo={}):
global powerstate, powertime, clearpowermessage
if opts.headless:
return
status = consolename
info = []
for statekey in stateinfo:
@@ -454,8 +457,10 @@ def do_command(command, server):
currconsole = targpath
startrequest = {'operation': 'start', 'path': targpath,
'parameters': {}}
height, width = struct.unpack(
'hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, b'....'))[:2]
height, width = 31, 100
if not opts.headless:
height, width = struct.unpack(
'hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, b'....'))[:2]
startrequest['parameters']['width'] = width
startrequest['parameters']['height'] = height
for param in argv[2:]:
@@ -623,19 +628,21 @@ def startconsole(nodename):
signal.signal(signal.SIGWINCH, do_resize)
didconsole = True
consolename = nodename
tty.setraw(sys.stdin.fileno())
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl | os.O_NONBLOCK)
if not opts.headless:
tty.setraw(sys.stdin.fileno())
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl | os.O_NONBLOCK)
inconsole = True
check_automation('') # give any leading 'sends' a chance
def quitconfetty(code=0, fullexit=False, fixterm=True):
global inconsole
global currconsole
global didconsole
if fixterm or didconsole:
if (fixterm or didconsole) and not opts.headless:
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl ^ os.O_NONBLOCK)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl & ~os.O_NONBLOCK)
if oldtcattr is not None:
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, oldtcattr)
# Request default color scheme, to undo potential weirdness of terminal
@@ -654,13 +661,17 @@ def quitconfetty(code=0, fullexit=False, fixterm=True):
def get_session_node(shellargs):
# straight to node console
if len(shellargs) == 1 and ' ' not in shellargs[0]:
return shellargs[0]
targ = "/nodes/%s/console/session" % shellargs[0]
return targ, shellargs[0]
if len(shellargs) == 2 and shellargs[0] == 'start':
args = [s for s in shellargs[1].split('/') if s]
if len(args) == 4 and args[0] == 'nodes' and args[2] == 'console' and \
args[3] == 'session':
return args[1]
return None
return shellargs[1], args[1]
if len(args) == 5 and args[0] == 'nodes' and args[2] == 'shell' and \
args[3] == 'sessions':
return shellargs[1], args[1]
return None, None
def run_inline_command(path, arg, completion, **kwargs):
@@ -839,6 +850,20 @@ def check_escape_seq(currinput, filehandle):
currinput += filehandle.read()
return currinput
automation_directives = []
current_automation_directive = None
automation_map = {
'<up>': '\x1b[A',
'<down>': '\x1b[B',
'<right>': '\x1b[C',
'<left>': '\x1b[D',
'<enter>': '\r',
'<esc>': '\x1b',
'<tab>': '\t',
}
parser = optparse.OptionParser()
parser.add_option("-s", "--server", dest="netserver",
help="Confluent instance to connect to",
@@ -846,12 +871,64 @@ parser.add_option("-s", "--server", dest="netserver",
parser.add_option("-c", "--control", dest="controlpath",
help="Path to offer terminal control",
metavar="PATH")
parser.add_option('-a', '--automation', type='string', default=None,
help='Specify an automation script to run', metavar='SCRIPT')
parser.add_option('-e', '--headless', action='store_true', default=False,
help='Run in headless mode, which is designed for use with '
'automation scripts and disables interactive features')
parser.add_option(
'-m', '--mintime', default=0,
help='Minimum time to run or else pause for input (used to keep a '
'terminal from closing quickly on error)')
opts, shellargs = parser.parse_args()
def parse_automation_script(script, session_node):
global current_automation_directive
for line in script.splitlines():
line = line.strip()
if not line or line.startswith('#'):
continue
if line.startswith('exit'):
automation_directives.append(('exit', None))
continue
if ' ' not in line:
sys.stderr.write("Invalid line in automation script: %s\n" % line)
continue
directive, arg = line.split(' ', 1)
directive = directive.strip().lower()
if directive not in ('expect', 'send', 'forget'):
sys.stderr.write("Unknown directive in automation script: %s\n" % directive)
continue
arg = arg.strip()
origarg = arg
if arg[0] not in ('"', "'"):
arg = '"' + arg + '"'
if arg[0] == "'" and arg[-1] == "'":
# do not process '<>' sequences in single quotes
arg = arg[1:-1]
arg = bytes(arg, "utf-8").decode("unicode_escape")
elif arg[0] == '"' and arg[-1] == '"':
arg = bytes(arg[1:-1], "utf-8").decode("unicode_escape")
for key, value in automation_map.items():
arg = arg.replace(key, value)
arg = re.sub(r'<env:(\w+)>', lambda m: os.environ[m.group(1)], arg)
if '{' in arg: # support confluent expressions
for res in session.create('/nodes/{0}/attributes/expression'.format(session_node),
{'expression': arg}):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
sys.exit(1)
if 'value' in res:
arg = res['value']
automation_directives.append((directive, arg, origarg))
if automation_directives:
current_automation_directive = automation_directives.pop(0)
if opts.headless and current_automation_directive[0] == 'expect':
sys.stdout.write(f'Expecting {repr(current_automation_directive[2])}\r\n')
sys.stdout.flush()
username = None
passphrase = None
def server_connect():
@@ -904,6 +981,7 @@ def main():
# sys.stdout.write('\x1b[H\x1b[J')
# sys.stdout.flush()
global powerstate, powertime, clearpowermessage
if sys.stdout.isatty():
@@ -917,10 +995,13 @@ def main():
doexit = False
inconsole = False
pendingcommand = ""
session_node = get_session_node(shellargs)
targ, session_node = get_session_node(shellargs)
if session_node is not None:
consoleonly = True
do_command("start /nodes/%s/console/session" % session_node, netserver)
if opts.automation:
with open(opts.automation) as f:
parse_automation_script(f.read(), session_node)
do_command("start %s" % targ, netserver)
doexit = True
elif shellargs:
do_command(shellargs, netserver)
@@ -931,9 +1012,13 @@ def main():
while inconsole or not doexit:
if inconsole:
if opts.headless:
handles = [session.connection]
else:
handles = (sys.stdin, session.connection)
try:
rdylist, _, _ = select.select(
(sys.stdin, session.connection), (), (), 10)
handles, (), (), 10)
except select.error:
rdylist = ()
for fh in rdylist:
@@ -948,8 +1033,9 @@ def main():
except IOError:
pass
if powerstate is None or powertime < time.time() - 10: # Check powerstate every 10 seconds
if powerstate == None:
powerstate = True
powertime = time.time()
powerstate = True
check_power_state()
else:
currcommand = prompt()
@@ -964,8 +1050,81 @@ def main():
sys.stdout.write('Lost connection to server')
quitconfetty(fullexit=True)
sgr_re = re.compile(r'(\x1b\[[0-9;]*m)')
sgr_parameters_re = re.compile(r'\x1b\[([0-9;]*)m')
fgcolor = None
bgcolor = None
fgshifted = False
pendseq = ''
automation_check = ''
def check_automation(data):
global automation_check
global current_automation_directive
if type(data) != str:
data = data.decode('utf-8', errors='ignore')
while current_automation_directive:
if current_automation_directive[0] == 'forget' and data:
current_automation_directive = None
automation_check = ''
if automation_directives:
current_automation_directive = automation_directives.pop(0)
if opts.headless and current_automation_directive[0] == 'expect':
sys.stdout.write(f'Expecting {repr(current_automation_directive[2])}\n')
sys.stdout.flush()
return
if current_automation_directive[0] == 'expect':
expected = current_automation_directive[1]
combined = automation_check + data
if expected and expected in combined:
data = data[combined.rindex(expected) + len(expected):]
if opts.headless:
sys.stdout.write(f'Detected {repr(current_automation_directive[2])}\r\n')
sys.stdout.flush()
current_automation_directive = None
automation_check = ''
if automation_directives:
current_automation_directive = automation_directives.pop(0)
if opts.headless and current_automation_directive[0] == 'expect':
sys.stdout.write(f'Expecting {repr(current_automation_directive[2])}\r\n')
sys.stdout.flush()
else:
# Check if there's potential start of expected data in the incoming data
combined = automation_check + data
automation_check = ''
for i in range(1, min(len(expected), len(combined)) + 1):
if expected.startswith(combined[-i:]):
automation_check = combined[-i:]
return # wait for next check
elif current_automation_directive[0] == 'send':
data = ''
automation_check = ''
if opts.headless:
sys.stdout.write(f'Sending {repr(current_automation_directive[2])}\r\n')
sys.stdout.flush()
if current_automation_directive[1]:
tlvdata.send(session.connection, current_automation_directive[1])
current_automation_directive = None
if automation_directives:
current_automation_directive = automation_directives.pop(0)
if opts.headless and current_automation_directive[0] == 'expect':
sys.stdout.write(f'Expecting {repr(current_automation_directive[2])}\r\n')
sys.stdout.flush()
elif current_automation_directive[0] == 'exit':
if opts.headless:
sys.stdout.write('Automation completed\r\n')
sys.stdout.flush()
return True
if opts.headless and not current_automation_directive:
sys.stdout.write('Automation completed\r\n')
sys.stdout.flush()
return True
return False
def consume_termdata(fh, bufferonly=False):
global clearpowermessage
global fgcolor, bgcolor, fgshifted, pendseq
try:
data = tlvdata.recv(fh)
except Exception:
@@ -974,7 +1133,64 @@ def consume_termdata(fh, bufferonly=False):
updatestatus(data)
return ''
if data is not None:
data = client.stringify(data)
shouldexit = check_automation(data)
if opts.headless:
if shouldexit:
quitconfetty(fullexit=True)
return ''
indata = pendseq + client.stringify(data)
pendseq = ''
data = ''
for segment in sgr_re.split(indata):
if sgr_re.match(segment): # it is an sgr, analyze, maybe replace
params = []
for parameters in sgr_parameters_re.findall(segment):
for param in parameters.split(';'):
params.append(param)
if param == '0':
fgcolor = None
bgcolor = None
try:
ival = int(param)
except ValueError:
continue
if 40 <= ival <= 47 or 100 <= ival <= 107:
bgcolor = ival
if 30 <= ival <= 37 or 90 <= ival <= 97:
fgcolor = ival
if bgcolor is not None:
fgindicated = False
for idx, param in enumerate(params):
try:
ival = int(param)
except ValueError:
continue
if 30 <= ival <= 37 and (bgcolor % 10 == ival % 10):
fgindicated = True
fgshifted = True
ival += 60
params[idx] = str(ival)
if not fgindicated and fgcolor is not None:
if bgcolor and (bgcolor % 10) == (fgcolor % 10):
fgshifted = True
params.append(str((fgcolor % 10) + 90))
elif fgshifted:
params.append(str(fgcolor))
segment = '\x1b[' + ';'.join(str(p) for p in params) + 'm'
data += segment
# defer any partial ansi escape sequence for a later pass
escidx = segment.rfind('\x1b[')
if escidx >= 0:
for chr in segment[escidx + 2:]:
if 0x40 <= ord(chr) <= 0x7e:
break
else:
# incomplete escape sequence, don't print it yet
data = data[:-len(segment) + escidx]
pendseq = segment[escidx:]
if not pendseq and segment and segment[-1] == '\x1b':
data = data[:-1]
pendseq = '\x1b'
if clearpowermessage:
sys.stdout.write("\x1b[2J\x1b[;H")
clearpowermessage = False
@@ -1001,6 +1217,8 @@ def consume_termdata(fh, bufferonly=False):
# this scenario comfortable that it
# will come out soon enough
pass
if shouldexit:
quitconfetty(fullexit=True)
else:
deadline = 5
connected = False
+42 -25
View File
@@ -1,8 +1,9 @@
#!/usr/bin/python2
#!/usr/bin/python3
import optparse
import signal
import sys
import os
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
@@ -17,18 +18,16 @@ import confluent.client as client
import confluent.sortutil as sortutil
def lookupdata(data, key):
ret = data.get(key, {}).get('value', '')
if ret is None:
ret = ''
return ret
def main():
argparser = optparse.OptionParser(
usage='''\n %prog noderange -o ansible.hosts
\n ''')
usage='''\n %prog noderange -o ansible.hosts -a
''')
argparser.add_option('-o', '--output',
help='Ansible hosts file')
help='Writes an Ansible hosts file')
argparser.add_option('-a', '--append', action='store_true',
help='Appends to existing hosts file')
(options, args) = argparser.parse_args()
try:
noderange = args[0]
@@ -45,24 +44,42 @@ def main():
if node not in databynode:
databynode[node] = {}
databynode[node].update(res['databynode'][node])
nodesbygroup = {}
with open(options.output, 'w') as importfile:
needempty = False
for node in sortutil.natural_sort(databynode):
data = databynode[node]
if not data.get('groups', []):
importfile.write(node + '\n')
needempty = True
for g in data.get('groups', []):
if g not in nodesbygroup:
nodesbygroup[g] = set([node])
for node in sortutil.natural_sort(databynode):
data = databynode[node]
groups = data.get('groups', [])
if not groups:
nodesbygroup.setdefault('', set()).add(node.strip().lower())
else:
for g in groups:
nodesbygroup.setdefault(g, set()).add(node.strip().lower())
existing_data = {}
if options.append and os.path.exists(options.output):
current_group = ''
with open(options.output, 'r') as f:
for line in f:
line = line.strip().lower()
if not line:
continue
if line.startswith('[') and line.endswith(']'):
current_group = line[1:-1]
existing_data.setdefault(current_group, set())
else:
nodesbygroup[g].add(node)
if needempty:
importfile.write('\n')
for group in sortutil.natural_sort(nodesbygroup):
importfile.write('[{0}]\n'.format(group))
for node in sortutil.natural_sort(nodesbygroup[group]):
existing_data.setdefault(current_group, set()).add(line)
for group, nodes in nodesbygroup.items():
nodes = {n.strip().lower() for n in nodes}
current_nodes = existing_data.get(group, set())
new_nodes = nodes - current_nodes
if new_nodes:
existing_data.setdefault(group, set()).update(nodes)
with open(options.output, 'w') as importfile:
for group in sortutil.natural_sort(existing_data.keys()):
if group:
importfile.write('[{0}]\n'.format(group))
for node in sortutil.natural_sort(existing_data[group]):
importfile.write('{0}\n'.format(node))
importfile.write('\n')
+9 -2
View File
@@ -118,6 +118,7 @@ def main():
ap.add_argument('-a', '--attrib', help='Pull ip addresses and hostnames from attribute database', action='store_true')
ap.add_argument('-i', '--ip', help='Expression to generate addresses (e.g. 172.16.1.{n1} or fd2b:246f:8a50::{n1:x})')
ap.add_argument('-n', '--name', help='Expression for name to add ({node}-compute, etc). If unspecified, "{node} {node}.{dns.domain}" will be used', action='append')
ap.add_argument('-f', '--fqdn-first', help='Put the FQDN first in the hosts entries', action='store_true')
args = ap.parse_args()
c = client.Command()
if args.name:
@@ -157,7 +158,7 @@ def main():
elif attrib.endswith('.ipv6_address') and val:
ip6bynode[node][currnet] = val.split('/', 1)[0]
elif attrib.endswith('.hostname'):
namesbynode[node][currnet] = re.split('\s+|,', val)
namesbynode[node][currnet] = re.split(r'\s+|,', val)
for node in ip4bynode:
mydomain = domainsbynode.get(node, None)
for ipdb in (ip4bynode, ip6bynode):
@@ -173,7 +174,13 @@ def main():
break
else:
for name in list(names):
names.append('{0}.{1}'.format(name, mydomain))
fqdn = '{0}.{1}'.format(name, mydomain)
if args.fqdn_first:
# Insert FQDN at the beginning if --fqdn-first flag is set
names.insert(0, fqdn)
else:
# Otherwise, append FQDN at the end (original behavior)
names.append(fqdn)
names = ' '.join(names)
merger.add_entry(ipdb[node][currnet], names)
merger.write_out('/etc/whatnowhosts')
+2
View File
@@ -79,6 +79,8 @@ def collect_attribute_data(databynode, node):
xcatattrs['groups'] = ','.join(data.get('groups', []))
xcatattrs['bmc'] = data.get('hardwaremanagement.manager', {}).get(
'value', None)
if xcatattrs['bmc']:
xcatattrs['bmc'] = xcatattrs['bmc'].split('/', 1)[0]
xcatattrs['mpa'] = data.get('enclosure.manager', {}).get(
'value', None)
xcatattrs['slotid'] = data.get('enclosure.bay', {}).get(
+39 -19
View File
@@ -8,30 +8,35 @@ import os
import subprocess
import sys
def create_image(directory, image, label=None):
ents = 0
datasz = 512
for dir in os.walk(sys.argv[1]):
ents += 1
for filen in dir[2]:
def create_image(directory, image, label=None, esize=0, totalsize=None):
if totalsize:
datasz = totalsize * 1048576
else:
ents = 0
datasz = 512 + (esize * 1048576)
for dir in os.walk(sys.argv[1]):
ents += 1
filename = os.path.join(dir[0], filen)
currsz = os.path.getsize(filename)
# assuming up to 65k cluster
currsz = (currsz // 512 +1) * 512
datasz += currsz
datasz += ents * 32768
datasz = datasz // 512 + 1
for filen in dir[2]:
ents += 1
filename = os.path.join(dir[0], filen)
currsz = os.path.getsize(filename)
# assuming up to 65k cluster
currsz = (currsz // 512 + 1) * 512
datasz += currsz
datasz += ents * 32768
datasz = datasz // 65536 + 1
with open(image, 'wb') as imgfile:
imgfile.seek(datasz * 512 - 1)
imgfile.seek(datasz * 65536 - 1)
imgfile.write(b'\x00')
if label:
# 4 heads, 32 sectors, means 65k per track
subprocess.check_call(['mformat', '-i', image, '-v', label,
'-r', '16', '-d', '1', '-t', str(datasz),
'-s', '1','-h', '1', '::'])
'-s', '32','-h', '4', '::'])
else:
subprocess.check_call(['mformat', '-i', image, '-r', '16', '-d', '1', '-t',
str(datasz), '-s', '1','-h', '1', '::'])
str(datasz), '-s', '32','-h', '4', '::'])
# Some clustered filesystems will have the lock from mformat
# linger after close (mformat doesn't unlock)
# do a blocking wait for shared lock and then explicitly
@@ -56,6 +61,21 @@ if __name__ == '__main__':
sys.argv[0]))
sys.exit(1)
label = None
if len(sys.argv) > 3:
label = sys.argv[3]
create_image(sys.argv[1], sys.argv[2], label)
args = sys.argv
esize = 0
try:
earg = args.index('-e')
esize = int(args[earg + 1])
args = args[:earg] + args[earg +2:]
except ValueError:
pass
totsize = None
try:
earg = args.index('-s')
totsize = int(args[earg + 1])
args = args[:earg] + args[earg +2:]
except ValueError:
pass
if len(args) > 3:
label = args[3]
create_image(args[1], args[2], label, esize, totsize)
+213
View File
@@ -0,0 +1,213 @@
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2016-2017 Lenovo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from collections import deque
import optparse
import os
import select
import signal
import subprocess
import sys
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
pass
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
if path.startswith('/opt'):
sys.path.append(path)
import confluent.client as client
import confluent.sortutil as sortutil
devnull = None
def run_automation(noderange, category, c):
automationbynode = {}
for res in c.update('/noderange/{0}/deployment/remote_config/run'.format(noderange), {
'category': category,
}):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
exitcode |= res.get('errorcode', 1)
if 'created' in res:
nodename = res['created'].split('/')[2]
automationbynode[nodename] = res['created']
while automationbynode:
for node in list(automationbynode):
for res in c.read(automationbynode[node]):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
exitcode |= res.get('errorcode', 1)
for result in res.get('results', []):
sys.stdout.write('{0}: Task [{1}] {2}\n'.format(
node, result['task_name'], result['state']))
for warning in result.get('warnings', []):
sys.stderr.write('{0}: [WARNING] {1}\n'.format(node, warning))
if 'errorinfo' in result:
for errorline in result['errorinfo'].splitlines():
sys.stderr.write('{0}: [ERROR] {1}\n'.format(node, errorline))
if res.get('complete', False):
del automationbynode[node]
sys.stdout.write('{0}: Automation complete\n'.format(node))
def run():
global devnull
devnull = open(os.devnull, 'rb')
argparser = optparse.OptionParser(
usage="Usage: %prog [options] noderange commandexpression",
epilog="Expressions are the same as in attributes, e.g. "
"'ipmitool -H {hardwaremanagement.manager}' will be expanded.")
argparser.add_option('-f', '-c', '--count', type='int', default=168,
help='Number of commands to run at a time')
argparser.add_option('-k', '--security', action='store_true',
help='Update SSH setup')
argparser.add_option('-F', '--sync', action='store_true',
help='Run the syncfiles associated with the currently completed OS profile on the noderange')
argparser.add_option('-P', '--scripts',
help='Re-run specified scripts, with full path under scripts, e.g. post.d/first,firstboot.d/second')
argparser.add_option('-A', '--automation',
help='Run the automation scripts associated with the current OS profile on the noderange, specifying category (onboot.d/firstboot.d/post.d)')
argparser.add_option('-m', '--maxnodes', type='int',
help='Specify a maximum number of '
'nodes to run remote ssh command to, '
'prompting if over the threshold')
# among other things, FD_SETSIZE limits. Besides, spawning too many
# processes can be unkind for the unaware on memory pressure and such...
#argparser.disable_interspersed_args()
(options, args) = argparser.parse_args()
if len(args) < 1:
argparser.print_help()
sys.exit(1)
client.check_globbing(args[0])
concurrentprocs = options.count
c = client.Command()
currprocs = 0
all = set([])
poller = select.epoll()
pipedesc = {}
pendingexecs = deque()
exitcode = 0
c.stop_if_noderange_over(args[0], options.maxnodes)
if options.automation:
run_automation(args[0], options.automation, c)
nodemap = {}
cmdparms = []
nodes = []
cmdstorun = []
if options.security:
cmdstorun.append(['run_remote', 'setupssh'])
if options.sync:
cmdstorun.append(['run_remote_python', 'syncfileclient'])
if options.scripts:
for script in options.scripts.split(','):
cmdstorun.append(['run_remote', script])
if not cmdstorun:
if options.automation:
sys.exit(0)
argparser.print_help()
sys.exit(1)
for res in c.read('/noderange/{0}/nodes/'.format(args[0])):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
exitcode |= res.get('errorcode', 1)
break
node = res['item']['href'][:-1]
nodes.append(node)
idxbynode = {}
cmdvbase = ['bash', '/etc/confluent/functions']
for sshnode in nodes:
idxbynode[sshnode] = 1
cmdv = ['ssh', sshnode] + cmdvbase + cmdstorun[0]
if currprocs < concurrentprocs:
currprocs += 1
run_cmdv(sshnode, cmdv, all, poller, pipedesc)
else:
pendingexecs.append((sshnode, cmdv))
if not all or exitcode:
sys.exit(exitcode)
rdy = poller.poll(10)
while all:
pernodeout = {}
for r in rdy:
r = r[0]
desc = pipedesc[r]
r = desc['file']
node = desc['node']
data = True
singlepoller = select.epoll()
singlepoller.register(r, select.EPOLLIN)
while data and singlepoller.poll(0):
data = r.readline()
if data:
if desc['type'] == 'stdout':
if node not in pernodeout:
pernodeout[node] = []
pernodeout[node].append(data)
else:
data = client.stringify(data)
sys.stderr.write('{0}: {1}'.format(node, data))
sys.stderr.flush()
else:
pop = desc['popen']
ret = pop.poll()
if ret is not None:
exitcode = exitcode | ret
all.discard(r)
poller.unregister(r)
r.close()
if desc['type'] == 'stdout':
if idxbynode[node] < len(cmdstorun):
cmdv = ['ssh', sshnode] + cmdvbase + cmdstorun[idxbynode[node]]
idxbynode[node] += 1
run_cmdv(node, cmdv, all, poller, pipedesc)
elif pendingexecs:
node, cmdv = pendingexecs.popleft()
run_cmdv(node, cmdv, all, poller, pipedesc)
singlepoller.close()
for node in sortutil.natural_sort(pernodeout):
for line in pernodeout[node]:
line = client.stringify(line)
line = line.lstrip('\x08')
sys.stdout.write('{0}: {1}'.format(node, line))
sys.stdout.flush()
if all:
rdy = poller.poll(10)
sys.exit(exitcode)
def run_cmdv(node, cmdv, all, poller, pipedesc):
nopen = subprocess.Popen(
cmdv, stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pipedesc[nopen.stdout.fileno()] = {'node': node, 'popen': nopen,
'type': 'stdout', 'file': nopen.stdout}
pipedesc[nopen.stderr.fileno()] = {'node': node, 'popen': nopen,
'type': 'stderr', 'file': nopen.stderr}
all.add(nopen.stdout)
poller.register(nopen.stdout, select.EPOLLIN)
all.add(nopen.stderr)
poller.register(nopen.stderr, select.EPOLLIN)
if __name__ == '__main__':
run()
+21
View File
@@ -22,6 +22,7 @@ import optparse
import os
import signal
import sys
import shlex
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
@@ -53,6 +54,8 @@ argparser.add_option('-p', '--prompt', action='store_true',
argparser.add_option('-m', '--maxnodes', type='int',
help='Prompt if trying to set attributes on more '
'than specified number of nodes')
argparser.add_option('-s', '--set', dest='set', metavar='settings.batch',
default=False, help='set attributes using a batch file')
(options, args) = argparser.parse_args()
@@ -109,10 +112,28 @@ elif options.clear or options.environment or options.prompt:
sys.stderr.write('Attribute names required with specified options\n')
argparser.print_help()
exitcode = 400
elif options.set:
arglist = [noderange]
showtype='current'
argfile = open(options.set, 'r')
argset = argfile.readline()
while argset:
try:
argset = argset[:argset.index('#')]
except ValueError:
pass
argset = argset.strip()
if argset:
arglist += shlex.split(argset)
argset = argfile.readline()
session.stop_if_noderange_over(noderange, options.maxnodes)
exitcode=client.updateattrib(session,arglist,nodetype, noderange, options, None)
if exitcode != 0:
sys.exit(exitcode)
# Lists all attributes
if len(args) > 0:
# setting output to all so it can search since if we do have something to search, we want to show all outputs even if it is blank.
if requestargs is None:
+121
View File
@@ -0,0 +1,121 @@
#!/usr/libexec/platform-python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2015-2017 Lenovo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__author__ = 'tkucherera'
from getpass import getpass
import optparse
import os
import signal
import sys
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
pass
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
if path.startswith('/opt'):
sys.path.append(path)
import confluent.client as client
argparser = optparse.OptionParser(usage="Usage: %prog <noderange> <username> <new_password>")
argparser.add_option('-m', '--maxnodes', type='int',
help='Number of nodes to affect before prompting for confirmation')
argparser.add_option('-p', '--prompt', action='store_true',
help='Prompt for password values interactively')
argparser.add_option('-e', '--environment', action='store_true',
help='Set passwod, but from environment variable of '
'same name')
(options, args) = argparser.parse_args()
try:
noderange = args[0]
username = args[1]
except IndexError:
argparser.print_help()
sys.exit(1)
client.check_globbing(noderange)
session = client.Command()
exitcode = 0
if options.prompt:
oneval = 1
twoval = 2
while oneval != twoval:
oneval = getpass('Enter pass for {0}: '.format(username))
twoval = getpass('Confirm pass for {0}: '.format(username))
if oneval != twoval:
print('Values did not match.')
new_password = twoval
elif len(args) == 3:
if options.environment:
key = args[2]
new_password = os.environ.get(key, os.environ[key.upper()])
else:
new_password = args[2]
else:
argparser.print_help()
sys.exit(1)
errorNodes = set([])
uid_dict = {}
session.stop_if_noderange_over(noderange, options.maxnodes)
for rsp in session.read('/noderange/{0}/configuration/management_controller/users/all'.format(noderange)):
databynode = rsp["databynode"]
for node in databynode:
if 'error' in rsp['databynode'][node]:
print(node, ':', rsp['databynode'][node]['error'])
errorNodes.add(node)
continue
for user in rsp['databynode'][node]['users']:
if user['username'] == username:
if not user['uid'] in uid_dict:
uid_dict[user['uid']] = node
continue
uid_dict[user['uid']] = uid_dict[user['uid']] + ',{}'.format(node)
break
if not uid_dict:
print("Error: Could not reach target node's bmc user")
sys.exit(1)
for uid in uid_dict:
success = session.simple_noderange_command(uid_dict[uid], 'configuration/management_controller/users/{0}'.format(uid), new_password, key='password', errnodes=errorNodes) # = 0 if successful
allNodes = set([])
for node in session.read('/noderange/{0}/nodes/'.format(noderange)):
if 'error' in node and success != 0:
sys.exit(success)
allNodes.add(node['item']['href'].replace("/", ""))
goodNodes = allNodes - errorNodes
for node in goodNodes:
print(node + ": Password Change Successful")
sys.exit(success)
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/python3
import os
import sys
from cryptography import x509
from cryptography.hazmat.primitives import hashes
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
if path.startswith('/opt'):
sys.path.append(path)
import confluent.client as client
def removebmccacert(noderange, certid, cmd):
for res in cmd.delete(f'/noderange/{noderange}/configuration/management_controller/certificate_authorities/{certid}'):
print(repr(res))
def listbmccacerts(noderange, cmd):
certids = []
for res in cmd.read(f'/noderange/{noderange}/configuration/management_controller/certificate_authorities'):
certids.append(res.get('item', {}).get('href', ''))
for certid in certids:
for res in cmd.read(f'/noderange/{noderange}/configuration/management_controller/certificate_authorities/{certid}'):
for node in res.get('databynode', {}):
certdata = res['databynode'][node].get('pem', {}).get('value', '')
summary = ''
if not certdata:
continue
san = res['databynode'][node].get('san', {}).get('value', '')
if san:
summary += f" SANs: {san}"
subject = res['databynode'][node].get('subject', {}).get('value', '')
if subject:
summary = subject
try:
cert = x509.load_pem_x509_certificate(certdata.encode())
sha256 = cert.fingerprint(hashes.SHA256()).hex().upper()
except Exception as e:
print(f"Error processing certificate for {node}: {e}", file=sys.stderr)
continue
summary += f" (SHA256={sha256})"
print(f"{node}: {certid}: {summary}")
def installbmccacert(noderange, certfile, cmd):
if certfile:
try:
with open(certfile, 'r') as f:
certdata = f.read()
except Exception as e:
print(f"Error reading certificate file: {e}", file=sys.stderr)
sys.exit(1)
# Simple validation: check if it starts and ends with the correct PEM markers
if not (certdata.startswith("-----BEGIN CERTIFICATE-----") and certdata.strip().endswith("-----END CERTIFICATE-----")):
print("Invalid certificate format. Must be a PEM encoded certificate.", file=sys.stderr)
sys.exit(1)
payload = {'pem': certdata}
for res in cmd.update(f'/noderange/{noderange}/configuration/management_controller/certificate_authorities', payload):
print(repr(res))
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Node certificate utility')
parser.add_argument('noderange', help='Node range to operate on')
subparsers = parser.add_subparsers(dest='command', help='Available commands')
# installbmccacert subcommand
install_parser = subparsers.add_parser('installbmccacert', help='Install BMC CA certificate')
install_parser.add_argument('filename', help='Certificate file to install')
remove_parser = subparsers.add_parser('removebmccacert', help='Remove BMC CA certificate')
remove_parser.add_argument('id', help='Certificate id to remove')
list_parser = subparsers.add_parser('listbmccacerts', help='List BMC CA certificates')
sign_bmc_parser = subparsers.add_parser('signbmccert', help='Sign BMC certificate')
sign_bmc_parser.add_argument('--days', type=int, help='Number of days the certificate is valid for')
sign_bmc_parser.add_argument('--added-names', type=str, help='Additional names to include in the certificate')
args = parser.parse_args()
c = client.Command()
if args.command == 'installbmccacert':
installbmccacert(args.noderange, args.filename, c)
elif args.command == 'removebmccacert':
removebmccacert(args.noderange, args.id, c)
elif args.command == 'listbmccacerts':
listbmccacerts(args.noderange, c)
elif args.command == 'signbmccert':
payload = {}
if args.days is not None:
payload['days'] = args.days
else:
print("Error: --days is required for signbmccert", file=sys.stderr)
sys.exit(1)
if args.added_names:
payload['added_names'] = args.added_names
for res in c.update(f'/noderange/{args.noderange}/configuration/management_controller/certificate/sign', payload):
print(repr(res))
else:
parser.print_help()
sys.exit(1)
+26 -11
View File
@@ -1,7 +1,7 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2017 Lenovo
# Copyright 2025 Lenovo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ argparser.add_option('-e', '--extra', dest='extra',
'to be extra configuration')
argparser.add_option('-x', '--exclude', dest='exclude',
action='store_true', default=False,
help='Treat positional arguments as items to not '
help='Treat named settings as items to not '
'examine, compare, or restore default')
argparser.add_option('-a', '--advanced', dest='advanced',
action='store_true', default=False,
@@ -73,7 +73,7 @@ argparser.add_option('-r', '--restoredefault', default=False,
dest='restoredefault', metavar="COMPONENT",
help='Restore the configuration of the node '
'to factory default for given component. '
'Currently only uefi is supported')
'Currently "uefi" and "bmc" are supported components')
argparser.add_option('-m', '--maxnodes', type='int',
help='Specify a maximum number of '
'nodes to configure, '
@@ -90,6 +90,18 @@ cfgpaths = {
'bmc.ipv4_gateway': (
'configuration/management_controller/net_interfaces/management',
'ipv4_gateway'),
'bmc.static_ipv6_addresses': (
'configuration/management_controller/net_interfaces/management',
'static_v6_addresses'),
'bmc.static_ipv6_gateway': (
'configuration/management_controller/net_interfaces/management',
'static_v6_gateway'),
'bmc.vlan_id': (
'configuration/management_controller/net_interfaces/management',
'vlan_id'),
'bmc.mac_address': (
'configuration/management_controller/net_interfaces/management',
'hw_addr'),
'bmc.hostname': (
'configuration/management_controller/hostname', 'hostname'),
}
@@ -289,19 +301,22 @@ else:
for path in queryparms:
if options.comparedefault:
continue
rc = client.print_attrib_path(path, session, list(queryparms[path]),
rcode |= client.print_attrib_path(path, session, list(queryparms[path]),
NullOpt(), queryparms[path])
if rc:
sys.exit(rc)
if printsys == 'all' or printextbmc or printbmc or printallbmc:
if printbmc or not printextbmc:
rcode = client.print_attrib_path(
rcode |= client.print_attrib_path(
'/noderange/{0}/configuration/management_controller/extended/all'.format(noderange),
session, printbmc, options, attrprefix='bmc.')
if options.extra:
rcode |= client.print_attrib_path(
'/noderange/{0}/configuration/management_controller/extended/extra'.format(noderange),
session, printextbmc, options)
if options.advanced:
rcode |= client.print_attrib_path(
'/noderange/{0}/configuration/management_controller/extended/extra_advanced'.format(noderange),
session, printextbmc, options)
else:
rcode |= client.print_attrib_path(
'/noderange/{0}/configuration/management_controller/extended/extra'.format(noderange),
session, printextbmc, options)
if printsys or options.exclude:
if printsys == 'all':
printsys = []
+707 -9
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/libexec/platform-python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2015 Lenovo
@@ -15,33 +15,346 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import base64
import optparse
import os
import shlex
import subprocess
import sys
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
if path.startswith('/opt'):
sys.path.append(path)
import confluent.client as client
import confluent.sortutil as sortutil
import confluent.logreader as logreader
import time
import select
import signal
import socket
import re
import tty
import termios
import fcntl
import confluent.screensqueeze as sq
try:
from PIL import Image, ImageDraw, ImageFont
except ImportError:
Image = None
try:
# sixel is optional, attempt to import but stub out if unavailable
import io
import sixel
class DumbWriter(sixel.SixelWriter):
def restore_position(self, output):
return
except ImportError:
class DumbWriter():
def draw(self, imgfile):
sys.stderr.write("PySixel not detected, Sixel format display not supported\n")
confettypath = os.path.join(os.path.dirname(sys.argv[0]), 'confetty')
argparser = optparse.OptionParser(
usage="Usage: %prog [options] node",
usage="Usage: %prog [options] <noderange> [kill][-- [passthroughoptions]]",
epilog="Command sequences are available while connected to a console, hit "
"ctrl-'e', then release ctrl, then 'c', then '?' for a full list. "
"For example, ctrl-'e', then 'c', then '.' will exit the current "
"console")
argparser.add_option('-a', '--automation', type='string', default=None,
help='Specify an automation script')
argparser.add_option('-t', '--tile', action='store_true', default=False,
help='Tile console windows in the terminal')
argparser.add_option('-e', '--headless', action='store_true', default=False,
help='Run in headless mode, which is designed for use with '
'automation scripts and disables interactive features')
argparser.add_option('-l', '--log', action='store_true', default=False,
help='Enter log replay mode instead of showing a live console')
argparser.add_option('-T', '--Timestamp', action='store_true', default=False,
help= 'Dump log in stdout with timestamps')
argparser.add_option('-s', '--screenshot', action='store_true', default=False,
help='Attempt to grab screenshot and render using kitty image protocol')
argparser.add_option('-i', '--interval', type='float',
help='Interval in seconds to redraw the screenshot. Currently only '
'works for one node')
argparser.add_option('-w','--windowed', action='store_true', default=False,
help='Open terminal windows for each node. The '
'environment variable NODECONSOLE_WINDOWED_COMMAND '
'should be set, which should be a text string corresponding '
'to a command that can be used to open a windowed console,'
' omitting the "nodeconsole <noderange>" part of the '
'command, for example, to open a set of consoles for a '
'range of nodes in separate xterm windows, set '
'NODECONSOLE_WINDOWED_COMMAND to "xterm -e". To open a '
'set of consoles for a range of nodes in separate '
'GNOME Terminal windows with a size of 100 columns and '
'31 rows, set NODECONSOLE_WINDOWED_COMMAND '
'to "gnome-terminal --geometry 100x31 --" or in a WSL '
'environment, to open a set of consoles for a range of '
'nodes in separate Windows Terminal windows, with the '
'title set for each node, set NODECONSOLE_WINDOWED_COMMAND'
' to "wt.exe wsl.exe -d AlmaLinux-8 '
'--shell-type login". If the NODECONSOLE_WINDOWED_COMMAND '
'environment variable isn\'t set, xterm will be used by'
'default.')
(options, args) = argparser.parse_args()
automation_args = []
if options.automation:
automation_args = ['-a', options.automation]
if options.headless:
automation_args += ['--headless']
oldtcattr = None
oldfl = None
def get_coords():
sys.stdout.write('\x1b[6n') #
sys.stdout.flush()
gotreply = select.select([sys.stdin,], [], [], 0.250)[0]
if gotreply:
response = ''
while select.select([sys.stdin,], [], [], 0.1)[0] and 'R' not in response:
response += sys.stdin.read()
coords = response.replace('R', '').split('[')[1].split(';')
#sys.stdout.write('\x1b[{}:{}H'.format(*coords))
def direct_console():
global oldtcattr
global oldfl
oldtcattr = termios.tcgetattr(sys.stdin.fileno())
oldfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
tty.setraw(sys.stdin.fileno())
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, oldfl | os.O_NONBLOCK)
def indirect_console():
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, oldfl & ~os.O_NONBLOCK)
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, oldtcattr)
def determine_tile_size(numnodes):
# for now, smash everything to a common aspect ratio. 16:11
# is pretty much wrong for everything, making 4:3 a bit too wide
# and 16:9 significantly too narrow, but it is serviceable
# An improvement could come with us owning the scaling
# instead of delegating to Kitty, which says if we specify both,
# we get stretching. In theory we should be able to get aspect correct
# from kitty by omitting, but:
# then we don't know how much to move the cursor left after draw_image
# Konsole won't scale at all with only partial scaling specified
cheight, cwidth, pixwidth, pixheight = sq.get_screengeom()
# 16:12 is to roughly account for the 'titles' of the tiles
ratio = (pixwidth / 16) / (pixheight / 12)
bestdeviation = None
bestdims = []
for i in range(1, numnodes + 1):
number = numnodes
while number % i != 0:
number += 1
columns = i
rows = number // i
deviation = abs(ratio - (columns / rows))
if bestdeviation is None:
bestdeviation = deviation
bestdims = [columns, rows]
elif deviation < bestdeviation:
bestdeviation = deviation
bestdims = [columns, rows]
# ok, the above algorithm can still pick things like
# 1 2 3
# 4
# So we will let it pick the number of rows, and
# then see if we can chop columns and still fit
while (bestdims[0] - 1) * bestdims[1] >= numnodes:
bestdims[0] = bestdims[0] - 1
cellswide = cwidth // bestdims[0]
cellshigh = cheight // bestdims[1]
tilewidth = cellswide * pixwidth / cwidth
tileheight = cellshigh * pixheight / cheight
if tilewidth > (tileheight * 16 / 11):
tilewidth = tileheight * 16 / 11
cellswide = int(tilewidth // (pixwidth / cwidth))
if tileheight > (tilewidth * 11 /16):
tileheight = tilewidth * 11 / 16
cellshigh = int(tileheight // (pixheight / cheight))
bestdims = bestdims + [cellswide, cellshigh, cellshigh * bestdims[1]]
# incur any scrolling we might get. This allows us to accurately
# save/restore cursor or even get coordinates without scrolling fouling
# the desired target
sys.stdout.write('\n' * bestdims[4])
sys.stdout.flush()
cursor_up(bestdims[4])
return bestdims
cursor_saved = False
def sticky_cursor():
global cursor_saved
# get cursor restore_position
if sys.stdin.isatty() and not cursor_saved:
try:
direct_console()
sys.stdout.write('\x1b7')
cursor_saved = True
finally:
indirect_console()
elif cursor_saved:
try:
direct_console()
sys.stdout.write('\x1b8')
finally:
indirect_console()
def cursor_up(count=1):
sys.stdout.write(f'\x1b[{count}A')
def cursor_down(count=1):
sys.stdout.write(f'\x1b[{count}B')
def cursor_right(count=1):
sys.stdout.write(f'\x1b[{count}C')
def cursor_left(count=1):
sys.stdout.write(f'\x1b[{count}D')
def cursor_save():
sys.stdout.write('\x1b7')
def cursor_restore():
sys.stdout.write('\x1b8')
def cursor_hide():
sys.stdout.write('\x1b[?25l')
def cursor_show():
sys.stdout.write('\x1b[?25h')
def get_pix_dimensions(width, height):
cheight, cwidth, pixwidth, pixheight = sq.get_screengeom()
imgwidth = int(pixwidth / cwidth * width)
imgheight = int(pixheight / cheight * height)
return imgwidth, imgheight
def draw_text(text, width, height):
if Image:
maxfntsize = 256
imgwidth, imgheight = get_pix_dimensions(width, height)
nerr = Image.new(mode='RGB', size=(imgwidth, imgheight), color='green')
nd = ImageDraw.Draw(nerr)
for txtpiece in text.split('\n'):
fntsize = 8
txtfont = ImageFont.truetype('DejaVuSans.ttf', size=fntsize)
while nd.textlength(txtpiece, font=txtfont) < int(imgwidth * 0.90):
fntsize += 1
txtfont = ImageFont.truetype('DejaVuSans.ttf', size=fntsize)
fntsize -= 1
if fntsize < maxfntsize:
maxfntsize = fntsize
hmargin = int(imgwidth * 0.05)
vmargin = int(imgheight * 0.10)
nd.text((hmargin, vmargin), text, font=txtfont)
nd.rectangle((0, 0, nerr.width - 1, nerr.height -1), outline='white')
outfile = io.BytesIO()
nerr.save(outfile, format='PNG')
data = base64.b64encode(outfile.getbuffer())
draw_image(data, width, height, doscale=False)
else:
sys.stdout.write(text)
cursor_left(len(text))
def draw_image(data, width, height, doscale=True):
imageformat = os.environ.get('CONFLUENT_IMAGE_PROTOCOL', 'kitty')
if doscale and Image and width:
bindata = base64.b64decode(data)
binfile = io.BytesIO()
binfile.write(bindata)
binfile.seek(0)
try:
img = Image.open(binfile)
except Exception as e:
errstr = 'Error rendering image:\n' + str(e)
return draw_text(errstr, width, height)
imgwidth, imgheight = get_pix_dimensions(width, height)
nimg = Image.new(mode='RGBA', size=(imgwidth, imgheight))
imgwidth -= 4
imgheight -= 4
hscalefact = imgwidth / img.width
vscalefact = imgheight / img.height
if hscalefact < vscalefact:
rzwidth = imgwidth
rzheight = int(img.height * hscalefact)
else:
rzwidth = int(img.width * vscalefact)
rzheight = imgheight
img = img.resize((rzwidth, rzheight))
nd = ImageDraw.Draw(nimg)
nd.rectangle((1, 1, rzwidth + 2, rzheight + 2), outline='black')
nd.rectangle((0, 0, rzwidth + 3, rzheight + 3), outline='white')
nimg.paste(img, box=(2, 2))
outfile = io.BytesIO()
nimg.save(outfile, format='PNG')
data = base64.b64encode(outfile.getbuffer())
if imageformat == 'sixel':
sixel_draw(data)
elif imageformat == 'iterm':
iterm_draw(data, width, height)
else:
kitty_draw(data, width, height)
def sixel_draw(data):
bindata = base64.b64decode(data)
binfile = io.BytesIO()
binfile.write(bindata)
binfile.seek(0)
DumbWriter().draw(binfile)
def iterm_draw(data, width, height):
if not height:
height = 'auto'
if not width:
width = 'auto'
bindata = base64.b64decode(data)
datalen = len(bindata)
sys.stdout.write(
'\x1b]1337;File=inline=1;width={};height={};size={}:'.format(width,height,datalen))
sys.stdout.write(data.decode('utf8'))
sys.stdout.write('\a')
sys.stdout.flush()
def kitty_draw(data, width, height):
preamble = '\x1b_Ga=T,f=100'
if height:
preamble += f',r={height},c={width}'
#sys.stdout.write(repr(preamble))
#sys.stdout.write('\xb[{}D'.format(len(repr(preamble))))
#return
first = True
while data:
chunk, data = data[:4096], data[4096:]
m = 1 if data else 0
if first:
sys.stdout.write('{},m={};'.format(preamble, m))
else:
sys.stdout.write('\x1b_Gm={};'.format(m))
sys.stdout.write(chunk.decode('utf8'))
sys.stdout.write('\x1b\\')
sys.stdout.flush()
pass_through_args = []
killcon = False
try:
noderange = args[0]
if len(args) > 1:
if args[1] == 'kill':
killcon = True
pass_through_args = args[1:]
args = args[:1]
except IndexError:
argparser.print_help()
sys.exit(1)
if len(args) != 1:
argparser.print_help()
sys.exit(1)
if options.log:
logname = args[0]
if not os.path.exists(logname) and logname[0] != '/':
@@ -51,6 +364,384 @@ if options.log:
sys.exit(1)
logreader.replay_to_console(logname)
sys.exit(0)
if options.Timestamp:
logname = args[0]
if not os.path.exists(logname) and logname[0] != '/':
logname = os.path.join('/var/log/confluent/consoles', logname)
if not os.path.exists(logname):
sys.stderr.write('Unable to locate {0} on local system\n'.format(logname))
sys.exit(1)
logreader.dump_to_console(logname)
sys.exit(0)
def prep_node_tile(node):
currcolcell, currrowcell = nodepositions[node]
if currcolcell:
cursor_right(currcolcell)
if currrowcell:
cursor_down(currrowcell)
sys.stdout.write('▏' + node)
cursor_left(len(node) + 1)
cursor_down()
def reset_cursor(node):
currcolcell, currrowcell = nodepositions[node]
if currcolcell:
cursor_left(currcolcell)
cursor_up(currrowcell + 1)
nodepositions = {}
numrows = 0
cwidth = 0
cheight = 0
imagedatabynode = {}
def redraw():
for node in imagedatabynode:
imgdata = imagedatabynode[node]
if node in nodepositions:
prep_node_tile(node)
cursor_save()
else:
if options.interval is not None:
if node != firstnodename:
sys.stderr.write('Multiple nodes not supported for interval')
sys.exit(1)
sticky_cursor()
sys.stdout.write('{}: '.format(node))
# one row is used by our own name, so cheight - 1 for that allowance
draw_image(imgdata.encode(), cwidth, cheight - 1 if cheight else cheight)
if node in nodepositions:
cursor_restore()
reset_cursor(node)
else:
sys.stdout.write('\n')
sys.stdout.flush()
resized = False
def do_screenshot():
global resized
global numrows
sess = client.Command()
if options.tile:
imageformat = os.environ.get('CONFLUENT_IMAGE_PROTOCOL', 'kitty')
if imageformat not in ('kitty', 'iterm'):
sys.stderr.write('Tiled screenshots only supported with kitty or iterm protocol')
sys.exit(1)
allnodes = []
numnodes = 0
for res in sess.read('/noderange/{}/nodes/'.format(args[0])):
allnodes.append(res['item']['href'].replace('/', ''))
numnodes += 1
resized = False
def do_resize(a=None, b=None):
global resized
if a:
resized = True
# on a window resize, clear the old stuff
# ideally we'd retain the images and redraw them
sys.stdout.write('\x1bc')
global numrows
global cwidth
global cheight
cols, rows, cwidth, cheight, numrows = determine_tile_size(numnodes)
currcol = 1
currcolcell = 0
currrowcell = 0
for node in allnodes:
nodepositions[node] = currcolcell, currrowcell
if currcol < cols:
currcol += 1
currcolcell += cwidth
else:
currcol = 1
currcolcell = 0
currrowcell += cheight
if a:
redraw()
do_resize()
signal.signal(signal.SIGWINCH, do_resize)
elif options.interval is not None:
sys.stdout.write('\x1bc')
firstnodename = None
dorefresh = True
vnconly = set([])
while dorefresh:
for res in sess.read('/noderange/{}/console/ikvm_screenshot'.format(args[0])):
for node in res.get('databynode', {}):
errorstr = ''
if not firstnodename:
firstnodename = node
error = res['databynode'][node].get('error')
if error and 'vnc available' in error:
vnconly.add(node)
continue
elif error:
errorstr = error
imgdata = res['databynode'][node].get('image', {}).get('imgdata', None)
if imgdata:
if len(imgdata) < 32: # We were subjected to error
errorstr = f'Unable to get screenshot'
if errorstr or imgdata:
draw_node(node, imgdata, errorstr, firstnodename, cwidth, cheight)
if asyncvnc:
urlbynode = {}
for node in vnconly:
for res in sess.update(f'/nodes/{node}/console/ikvm', {'method': 'unix'}):
url = res.get('item', {}).get('href')
if url:
urlbynode[node] = url
draw_vnc_grabs(urlbynode, cwidth, cheight)
if resized:
do_resize(True)
resized = False
elif vnconly:
sys.stderr.write("Require asyncvnc installed to do VNC screenshotting\n")
if options.interval is None:
dorefresh = False
else:
dorefresh = True
time.sleep(options.interval)
sys.exit(0)
try:
import asyncio, asyncvnc
except ImportError:
asyncvnc = None
def draw_vnc_grabs(urlbynode, cwidth, cheight):
asyncio.run(grab_vncs(urlbynode, cwidth, cheight))
async def grab_vncs(urlbynode, cwidth, cheight):
tasks = []
for node in urlbynode:
url = urlbynode[node]
tasks.append(asyncio.create_task(do_vnc_screenshot(node, url, cwidth, cheight)))
await asyncio.gather(*tasks)
async def my_opener(host, port):
# really, host is the unix
return await asyncio.open_unix_connection(host)
async def do_vnc_screenshot(node, url, cwidth, cheight):
async with asyncvnc.connect(url, opener=my_opener) as client:
# Retrieve pixels as a 3D numpy array
pixels = await client.screenshot()
# Save as PNG using PIL/pillow
image = Image.fromarray(pixels)
outfile = io.BytesIO()
image.save(outfile, format='PNG')
imgdata = base64.b64encode(outfile.getbuffer()).decode()
if imgdata:
draw_node(node, imgdata, '', '', cwidth, cheight)
def draw_node(node, imgdata, errorstr, firstnodename, cwidth, cheight):
imagedatabynode[node] = imgdata
if node in nodepositions:
prep_node_tile(node)
cursor_save()
else:
if options.interval is not None:
if node != firstnodename:
sys.stderr.write('Multiple nodes not supported for interval')
sys.exit(1)
sticky_cursor()
sys.stdout.write('{}: '.format(node))
# one row is used by our own name, so cheight - 1 for that allowance
if errorstr:
draw_text(errorstr, cwidth, cheight -1 if cheight else cheight)
else:
draw_image(imgdata.encode(), cwidth, cheight - 1 if cheight else cheight)
if node in nodepositions:
cursor_restore()
reset_cursor(node)
else:
sys.stdout.write('\n')
sys.stdout.flush()
if options.screenshot:
try:
cursor_hide()
do_screenshot()
except KeyboardInterrupt:
pass
finally:
cursor_show()
cursor_down(numrows)
sys.stdout.write('\n')
sys.exit(0)
def kill(noderange):
sess = client.Command()
envstring=os.environ.get('NODECONSOLE_WINDOWED_COMMAND')
if not envstring:
envstring = 'xterm'
nodes = []
for res in sess.read('/noderange/{0}/nodes/'.format(noderange)):
node = res.get('item', {}).get('href', '/').replace('/', '')
if not node:
sys.stderr.write(res.get('error', repr(res)) + '\n')
sys.exit(1)
nodes.append(node)
for node in nodes:
command = "ps auxww | grep {0} | grep console | egrep '\\b{1}\\b' | grep -v grep | awk '{{print $2}}'".format(envstring, node)
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
try:
process_id = stdout.decode('utf-8').split()[0]
except IndexError:
sys.stderr.write(node + ": console window not found \n")
continue
subprocess.Popen(["kill", process_id], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sys.exit(0)
def handle_geometry(envlist, sizegeometry, side_pad=0, top_pad=0, first=False):
if '-geometry' in envlist:
g_index = envlist.index('-geometry')
elif '-g' in envlist:
g_index = envlist.index('-g')
else:
g_index = 0
if g_index:
if first:
envlist[g_index+1] = '{0}+{1}+{2}'.format(envlist[g_index+1],side_pad, top_pad)
else:
envlist[g_index+1] = '{0}+{1}+{2}'.format(sizegeometry,side_pad, top_pad)
else:
envlist.insert(1, '-geometry')
envlist.insert(2, '{0}+{1}+{2}'.format(sizegeometry,side_pad, top_pad))
g_index = 1
return envlist
# add funcltionality to close/kill all open consoles
if killcon:
kill(noderange)
#added functionality for wcons
if options.windowed:
result=subprocess.Popen(['xwininfo', '-root'], stdout=subprocess.PIPE)
rootinfo=result.communicate()[0]
result.wait()
for line in rootinfo.decode('utf-8').split('\n'):
if 'Width' in line:
screenwidth = int(line.split(':')[1])
if 'Height' in line:
screenheight = int(line.split(':')[1])
envstring=os.environ.get('NODECONSOLE_WINDOWED_COMMAND')
if not envstring:
sizegeometry='100x31'
corrected_x, corrected_y = (13,84)
envlist = handle_geometry(['xterm'] + pass_through_args + ['-e'],sizegeometry, first=True)
#envlist=['xterm', '-bg', 'black', '-fg', 'white', '-geometry', '{sizegeometry}+0+0'.format(sizegeometry=sizegeometry), '-e']
else:
envlist=os.environ.get('NODECONSOLE_WINDOWED_COMMAND').split(' ')
if envlist[0] == 'xterm':
if '-geometry' in envlist:
g_index = envlist.index('-geometry')
elif '-g' in envlist:
g_index = envlist.index('-g')
else:
g_index = 0
if g_index:
envlist[g_index+1] = envlist[g_index+1] + '+0+0'
else:
envlist.insert(1, '-geometry')
envlist.insert(2, '100x31+0+0')
g_index = 1
nodes = []
sess = client.Command()
for res in sess.read('/noderange/{0}/nodes/'.format(args[0])):
node = res.get('item', {}).get('href', '/').replace('/', '')
if not node:
sys.stderr.write(res.get('error', repr(res)) + '\n')
sys.exit(1)
nodes.append(node)
if options.tile and not envlist[0] == 'xterm':
sys.stderr.write('[ERROR] UNSUPPORTED OPTIONS. \nWindowed and tiled consoles are only supported when using xterm \n')
sys.exit(1)
firstnode=nodes[0]
nodes.pop(0)
with open(os.devnull, 'wb') as devnull:
xopen=subprocess.Popen(envlist + [confettypath, '-c', '/tmp/controlpath-{0}'.format(firstnode)] + automation_args + ['-m', '5', 'start', '/nodes/{0}/console/session'.format(firstnode)] , stdin=devnull)
time.sleep(2)
s=socket.socket(socket.AF_UNIX)
winid=''
try:
s.connect('/tmp/controlpath-{firstnode}'.format(firstnode=firstnode))
s.recv(64)
s.send(b'GETWINID')
winid=s.recv(64).decode('utf-8')
except:
time.sleep(2)
# try to get id of first panel/xterm window using name
win=subprocess.Popen(['xwininfo', '-tree', '-root'], stdout=subprocess.PIPE)
wintr=win.communicate()[0]
for line in wintr.decode('utf-8').split('\n'):
if 'console: {firstnode}'.format(firstnode=firstnode) in line or 'confetty' in line:
win_obj = [ele for ele in line.split(' ') if ele.strip()]
winid = win_obj[0]
if winid:
firstnode_window=subprocess.Popen(['xwininfo', '-id', '{winid}'.format(winid=winid)], stdout=subprocess.PIPE)
xinfo=firstnode_window.communicate()[0]
xinfl = xinfo.decode('utf-8').split('\n')
for line in xinfl:
if 'Absolute upper-left X:' in line:
side_pad = int(line.split(':')[1])
elif 'Absolute upper-left Y:' in line:
top_pad = int(line.split(':')[1])
elif 'Width:' in line:
window_width = int(line.split(':')[1])
elif 'Height' in line:
window_height = int(line.split(':')[1])
elif '-geometry' in line:
l = re.split(' |x|-|\\+', line)
l_nosp = [ele for ele in l if ele.strip()]
wmxo = int(l_nosp[1])
wmyo = int(l_nosp[2])
sizegeometry = str(wmxo) + 'x' + str(wmyo)
else:
pass
window_width += side_pad*2
window_height += side_pad+top_pad
screenwidth -= wmxo
screenheight -= wmyo
currx = window_width
curry = 0
for node in sortutil.natural_sort(nodes):
if options.tile and envlist[0] == 'xterm':
corrected_x = currx
corrected_y = curry
xgeometry = '{0}+{1}+{2}'.format(sizegeometry, corrected_x, corrected_y)
currx += window_width
if currx + window_width >= screenwidth:
currx=0
curry += window_height
if curry > screenheight:
curry =top_pad
if not envstring:
envlist= handle_geometry(envlist, sizegeometry, corrected_x, corrected_y)
else:
if g_index:
envlist[g_index+1] = xgeometry
elif envlist[0] == 'xterm':
envlist=handle_geometry(envlist, sizegeometry, side_pad, top_pad)
side_pad+=(side_pad+1)
top_pad+=(top_pad+30)
else:
pass
with open(os.devnull, 'wb') as devnull:
xopen=subprocess.Popen(envlist + [confettypath, '-c', '/tmp/controlpath-{0}'.format(node)] + automation_args + ['-m', '5', 'start', '/nodes/{0}/console/session'.format(node)] , stdin=devnull)
sys.exit(0)
#end of wcons
if options.tile:
null = open('/dev/null', 'w')
nodes = []
@@ -62,29 +753,36 @@ if options.tile:
sys.exit(1)
nodes.append(node)
initial = True
in_tmux = False
pane = 0
sessname = 'nodeconsole_{0}'.format(os.getpid())
if os.environ.get("TMUX"):
initial = False
in_tmux = True
subprocess.call(['tmux', 'rename-session', sessname])
for node in sortutil.natural_sort(nodes):
panename = '{0}:{1}'.format(sessname, pane)
if initial:
initial = False
confetty_cmd = [confettypath] + automation_args + ['-m', '5', 'start', '/nodes/{0}/console/session'.format(node)]
subprocess.call(
['tmux', 'new-session', '-d', '-s',
sessname, '-x', '800', '-y',
'800', '{0} -m 5 start /nodes/{1}/console/session'.format(
confettypath, node)])
'800', ' '.join(shlex.quote(arg) for arg in confetty_cmd)])
else:
subprocess.call(['tmux', 'select-pane', '-t', sessname])
subprocess.call(['tmux', 'set-option', '-t', panename, 'pane-border-status', 'top'], stderr=null)
confetty_cmd = [confettypath] + automation_args + ['-m', '5', 'start', '/nodes/{0}/console/session'.format(node)]
subprocess.call(
['tmux', 'split', '-h', '-t', sessname,
'{0} -m 5 start /nodes/{1}/console/session'.format(
confettypath, node)])
' '.join(shlex.quote(arg) for arg in confetty_cmd)])
subprocess.call(['tmux', 'select-layout', '-t', sessname, 'tiled'], stdout=null)
pane += 1
subprocess.call(['tmux', 'select-pane', '-t', sessname])
subprocess.call(['tmux', 'set-option', '-t', panename, 'pane-border-status', 'top'], stderr=null)
os.execlp('tmux', 'tmux', 'attach', '-t', sessname)
if not in_tmux:
os.execlp('tmux', 'tmux', 'attach', '-t', sessname)
else:
os.execl(confettypath, confettypath, 'start',
'/nodes/{0}/console/session'.format(args[0]))
execl_args = [confettypath] + automation_args + ['start',
'/nodes/{0}/console/session'.format(args[0])]
os.execl(confettypath, *execl_args)
+107 -36
View File
@@ -48,8 +48,19 @@ def armonce(nr, cli):
pass
def setpending(nr, profile, cli):
args = {'deployment.pendingprofile': profile}
def setpending(nr, profile, profilebynodes, cli):
if profilebynodes:
for node in sortutil.natural_sort(profilebynodes):
prof = profilebynodes[node]
args = {'deployment.pendingprofile': prof, 'deployment.state': '', 'deployment.state_detail': ''}
if not prof.startswith('genesis-'):
args['deployment.stagedprofile'] = ''
args['deployment.profile'] = ''
for rsp in cli.update('/nodes/{0}/attributes/current'.format(node),
args):
pass
return
args = {'deployment.pendingprofile': profile, 'deployment.state': '', 'deployment.state_detail': ''}
if not profile.startswith('genesis-'):
args['deployment.stagedprofile'] = ''
args['deployment.profile'] = ''
@@ -67,8 +78,10 @@ def main(args):
ap = argparse.ArgumentParser(description='Deploy OS to nodes')
ap.add_argument('-c', '--clear', help='Clear any pending deployment action', action='store_true')
ap.add_argument('-n', '--network', help='Initiate deployment over PXE/HTTP', action='store_true')
ap.add_argument('-b', '--bootmethod', help='Specify network boot method (e.g., network, http)', default='network')
ap.add_argument('-p', '--prepareonly', help='Prepare only, skip any interaction with a BMC associated with this deployment action', action='store_true')
ap.add_argument('-m', '--maxnodes', help='Specifiy a maximum nodes to be deployed')
ap.add_argument('-r', '--redeploy', help='Redeploy nodes with the current or pending profile', action='store_true')
ap.add_argument('noderange', help='Set of nodes to deploy')
ap.add_argument('profile', nargs='?', help='Profile name to deploy')
args, extra = ap.parse_known_args(args)
@@ -78,48 +91,86 @@ def main(args):
if args.profile and not args.network:
sys.stderr.write('-n is a required argument currently to perform an install, optionally with -p\n')
return 1
if not args.profile and args.network:
if not args.profile and args.network and not args.redeploy:
sys.stderr.write('Both noderange and a profile name are required arguments to request a network deployment\n')
return 1
if args.clear and args.profile:
sys.stderr.write(
'The -c/--clear option should not be used with a profile, '
'it is a request to not deploy any profile, and will clear '
'whatever the current profile is without being specified\n')
return 1
if extra:
sys.stderr.write('Unrecognized arguments: ' + repr(extra) + '\n')
c = client.Command()
c.stop_if_noderange_over(args.noderange, args.maxnodes)
errnodes = set([])
if not args.clear and args.network and not args.prepareonly:
rc = c.simple_noderange_command(args.noderange, '/boot/nextdevice', 'network',
bootmode='uefi',
persistent=False,
errnodes=errnodes)
if errnodes:
sys.stderr.write(
'Unable to set boot device for following nodes: {0}\n'.format(
','.join(errnodes)))
return 1
rc |= c.simple_noderange_command(args.noderange, '/power/state', 'boot')
for rsp in c.read('/noderange/{0}/nodes/'.format(args.noderange)):
if 'error' in rsp:
sys.stderr.write(rsp['error'] + '\n')
sys.exit(1)
profilebynode = {}
if args.clear:
cleararm(args.noderange, c)
clearpending(args.noderange, c)
elif args.profile:
profnames = []
for prof in c.read('/deployment/profiles/'):
profname = prof.get('item', {}).get('href', None)
if profname:
profname = profname.replace('/', '')
profnames.append(profname)
if profname == args.profile:
break
else:
sys.stderr.write('The specified profile "{}" is not an available profile\n'.format(args.profile))
if profnames:
sys.stderr.write('The following profiles are available:\n')
for profname in profnames:
sys.stderr.write(' ' + profname + '\n')
else:
sys.stderr.write('No deployment profiles available, try osdeploy fiimport or imgutil capture\n')
elif args.redeploy:
hadpending = {}
for rsp in c.read('/noderange/{0}/attributes/current'.format(args.noderange)):
for node in rsp.get('databynode', {}):
nodeinfo = rsp['databynode'][node]
for attr in nodeinfo:
if attr == 'deployment.pendingprofile':
curr = nodeinfo[attr].get('value', '')
if curr:
hadpending[node] = True
profilebynode[node] = curr
if attr == 'deployment.stagedprofile':
curr = nodeinfo[attr].get('value', '')
if curr and node not in hadpending:
profilebynode[node] = curr
if attr == 'deployment.profile':
curr = nodeinfo[attr].get('value', '')
if curr and node not in profilebynode:
profilebynode[node] = curr
for lockinfo in c.read('/noderange/{0}/deployment/lock'.format(args.noderange)):
for node in lockinfo.get('databynode', {}):
lockstate = lockinfo['databynode'][node]['lock']['value']
if lockstate == 'locked':
lockednodes.append(node)
if args.profile and profilebynode:
sys.stderr.write('The -r/--redeploy option cannot be used with a profile, it redeploys the current or pending profile\n')
return 1
if args.profile or profilebynode:
lockednodes = []
for lockinfo in c.read('/noderange/{0}/deployment/lock'.format(args.noderange)):
for node in lockinfo.get('databynode', {}):
lockstate = lockinfo['databynode'][node]['lock']['value']
if lockstate == 'locked':
lockednodes.append(node)
if lockednodes:
sys.stderr.write('Requested noderange has nodes with locked deployment: ' + ','.join(lockednodes))
sys.stderr.write('\n')
sys.exit(1)
if args.profile:
profnames = []
for prof in c.read('/deployment/profiles/'):
profname = prof.get('item', {}).get('href', None)
if profname:
profname = profname.replace('/', '')
profnames.append(profname)
if profname == args.profile:
break
else:
sys.stderr.write('The specified profile "{}" is not an available profile\n'.format(args.profile))
if profnames:
sys.stderr.write('The following profiles are available:\n')
for profname in profnames:
sys.stderr.write(' ' + profname + '\n')
else:
sys.stderr.write('No deployment profiles available, try osdeploy import or imgutil capture\n')
sys.exit(1)
armonce(args.noderange, c)
setpending(args.noderange, args.profile, c)
setpending(args.noderange, args.profile, profilebynode, c)
else:
databynode = {}
for r in c.read('/noderange/{0}/attributes/current'.format(args.noderange)):
@@ -128,7 +179,7 @@ def main(args):
if node not in databynode:
databynode[node] = {}
for attr in dbn[node]:
if attr in ('deployment.pendingprofile', 'deployment.apiarmed', 'deployment.stagedprofile', 'deployment.profile'):
if attr in ('deployment.pendingprofile', 'deployment.apiarmed', 'deployment.stagedprofile', 'deployment.profile', 'deployment.state', 'deployment.state_detail'):
databynode[node][attr] = dbn[node][attr].get('value', '')
for node in sortutil.natural_sort(databynode):
profile = databynode[node].get('deployment.pendingprofile', '')
@@ -149,10 +200,30 @@ def main(args):
armed = ' (node authentication armed)'
else:
armed = ''
print('{0}: {1}{2}'.format(node, profile, armed))
stateinfo = ''
deploymentstate = databynode[node].get('deployment.state', '')
if deploymentstate:
statedetails = databynode[node].get('deployment.state_detail', '')
if statedetails:
stateinfo = '{}: {}'.format(deploymentstate, statedetails)
else:
stateinfo = deploymentstate
if stateinfo:
print('{0}: {1} ({2})'.format(node, profile, stateinfo))
else:
print('{0}: {1}{2}'.format(node, profile, armed))
sys.exit(0)
if args.network and not args.prepareonly:
return rc
if not args.clear and args.network and not args.prepareonly:
rc = c.simple_noderange_command(args.noderange, '/boot/nextdevice', args.bootmethod,
bootmode='uefi',
persistent=False,
errnodes=errnodes)
if errnodes:
sys.stderr.write(
'Unable to set boot device for following nodes: {0}\n'.format(
','.join(errnodes)))
return 1
rc |= c.simple_noderange_command(args.noderange, '/power/state', 'boot')
return 0
if __name__ == '__main__':
+73 -11
View File
@@ -50,19 +50,52 @@ columnmapping = {
}
#TODO: add chassis uuid
def register_endpoint(options, session, addr):
neednewline = False
current = 0
for rsp in session.update('/discovery/register', {'addresses': addr}):
if 'count' in rsp:
total = rsp['count']
elif total > 1:
current += 1
sys.stdout.write('\x1b[2K\r{0:.1f}% Scanned'.format(100 * current / total))
sys.stdout.flush()
neednewline = True
if 'created' in rsp:
if neednewline:
print('')
neednewline = False
print('Registered: {0}'.format(rsp['created']))
if neednewline:
print('')
def subscribe_discovery(options, session, subscribe, targ):
keyn = 'subscribe' if subscribe else 'unsubscribe'
payload = {keyn: targ}
if subscribe:
for rsp in session.update('/discovery/subscriptions/{0}'.format(targ), payload):
if 'status' in rsp:
print(rsp['status'])
else:
for rsp in session.delete('/discovery/subscriptions/{0}'.format(targ)):
if 'status' in rsp:
print(rsp['status'])
def print_disco(options, session, currmac, outhandler, columns):
procinfo = {}
for tmpinfo in session.read('/discovery/by-mac/{0}'.format(currmac)):
procinfo.update(tmpinfo)
if 'Switch' in columns or 'Port' in columns:
for tmpinfo in session.read(
'/networking/macs/by-mac/{0}'.format(currmac)):
if 'ports' in tmpinfo:
# The api sorts so that the most specific available value
# is last
procinfo.update(tmpinfo['ports'][-1])
if 'switch' in procinfo:
procinfo['port'] = procinfo['switchport']
else:
for tmpinfo in session.read(
'/networking/macs/by-mac/{0}'.format(currmac)):
if 'ports' in tmpinfo:
# The api sorts so that the most specific available value
# is last
procinfo.update(tmpinfo['ports'][-1])
record = []
for col in columns:
rawcol = columnmapping[col]
@@ -90,7 +123,7 @@ def process_header(header):
fields.append('serial')
elif datum == 'uuid':
fields.append('uuid')
elif datum in ('bmc', 'imm', 'xcc'):
elif datum in ('bmc', 'imm', 'xcc', 'ip'):
fields.append('hardwaremanagement.manager')
elif datum in ('bmc gateway', 'xcc gateway', 'imm gateway'):
fields.append('net.bmc.ipv4_gateway')
@@ -158,6 +191,7 @@ def import_csv(options, session):
if field in unique_fields:
unique_data[field] = set([])
broken = False
alldata=[]
for record in records:
currfields = list(fields)
nodedatum = {}
@@ -174,9 +208,15 @@ def import_csv(options, session):
nodedatum[currfield] = datum
if not datum_complete(nodedatum):
sys.exit(1)
alldata.append(nodedatum)
allthere = True
for nodedatum in alldata:
if not search_record(nodedatum, options, session) and not broken:
allthere = False
blocking_scan(session)
if not search_record(nodedatum, options, session):
break
for nodedatum in alldata:
if not allthere and not search_record(nodedatum, options, session):
sys.stderr.write(
"Could not match the following data: " +
repr(nodedatum) + '\n')
@@ -197,8 +237,12 @@ def import_csv(options, session):
print('Defined ' + res['created'])
else:
print(repr(res))
child = os.fork()
if child:
continue
for mac in maclist:
for res in session.update('/discovery/by-mac/{0}'.format(mac),
mysess = client.Command()
for res in mysess.update('/discovery/by-mac/{0}'.format(mac),
{'node': nodename}):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
@@ -208,6 +252,12 @@ def import_csv(options, session):
print('Discovered ' + res['assigned'])
else:
print(repr(res))
sys.exit(0)
while True:
try:
os.wait()
except ChildProcessError:
break
if exitcode:
sys.exit(exitcode)
@@ -320,7 +370,7 @@ def blocking_scan(session):
def main():
parser = optparse.OptionParser(
usage='Usage: %prog [list|assign|rescan|clear] [options]')
usage='Usage: %prog [list|assign|rescan|clear|subscribe|unsubscribe|register] [options]')
# -a for 'address' maybe?
# order by
# show state (discovered or..
@@ -358,9 +408,15 @@ def main():
parser.add_option('-o', '--order', dest='order',
help='Order output by given field', metavar='ORDER')
(options, args) = parser.parse_args()
if len(args) == 0 or args[0] not in ('list', 'assign', 'reassign', 'rescan', 'clear'):
if len(args) == 0 or args[0] not in ('list', 'assign', 'reassign', 'rescan', 'clear', 'subscribe', 'unsubscribe', 'register'):
parser.print_help()
sys.exit(1)
if args[0] == 'register' and len(args) != 2:
sys.stderr.write('Register requires target address or range (e.g. 192.168.2.30, 192.168.2.0/24, or 192.168.2.1-192.168.2.30)\n')
sys.exit(1)
if 'subscribe' in args[0] and len(args) != 2:
sys.stderr.write('subscribe/unsubscribe subcommands require switch name as argument\n')
sys.exit(1)
session = client.Command()
if args[0] == 'list':
list_discovery(options, session)
@@ -370,6 +426,12 @@ def main():
assign_discovery(options, session)
if args[0] == 'reassign':
assign_discovery(options, session, False)
if args[0] == 'register':
register_endpoint(options, session, args[1])
if args[0] == 'subscribe':
subscribe_discovery(options, session, True, args[1])
if args[0] == 'unsubscribe':
subscribe_discovery(options, session, False, args[1])
if args[0] == 'rescan':
blocking_scan(session)
print("Rescan complete")
+69 -7
View File
@@ -17,6 +17,7 @@
import codecs
from datetime import datetime as dt
from datetime import timedelta
import optparse
import os
import signal
@@ -41,7 +42,18 @@ argparser = optparse.OptionParser(
argparser.add_option('-m', '--maxnodes', type='int',
help='Specify a maximum number of '
'nodes to clear if clearing log, '
'prompting if over the threshold')
'prompting if over the threshold')
argparser.add_option('-l', '--lines', type='int',
help='return the last <n> entries '
'for each node in the eventlog. '
)
argparser.add_option('-t', '--timeframe', type='string',
help='return entries within a specified timeframe '
'for each node in the eventlog. This will return '
'entries from the last hours or days. '
'1h would be one hour, 4d would be four days. '
'format <num>h or <num>d'
)
(options, args) = argparser.parse_args()
try:
noderange = args[0]
@@ -66,8 +78,11 @@ exitcode = 0
def format_event(evt):
retparts = []
if 'timestamp' in evt and evt['timestamp'] is not None:
display = dt.strptime(evt['timestamp'], '%Y-%m-%dT%H:%M:%S')
retparts.append(display.strftime('%m/%d/%Y %H:%M:%S'))
try:
display = dt.strptime(evt['timestamp'], '%Y-%m-%dT%H:%M:%S')
retparts.append(display.strftime('%m/%d/%Y %H:%M:%S'))
except ValueError:
display = ''
dscparts = []
if evt.get('log_id', None):
retparts.append(evt['log_id'] + ':')
@@ -89,12 +104,34 @@ def format_event(evt):
msg = ''
return ' '.join(retparts) + msg
if deletemode:
func = session.delete
session.stop_if_noderange_over(noderange, options.maxnodes)
else:
func = session.read
if options.timeframe:
try:
delta = int(options.timeframe[:-1])
except ValueError:
argparser.print_help()
sys.exit(1)
if options.timeframe[-1].lower() == 'd':
tdelta = timedelta(days=delta)
elif options.timeframe[-1].lower() == 'h':
tdelta = timedelta(hours=delta)
else:
argparser.print_help()
sys.exit(1)
timeframe = dt.now() - tdelta
event_dict = {}
nodes = []
for res in session.read('/noderange/{0}/nodes/'.format(args[0])):
node = res.get('item', {}).get('href', '/').replace('/', '')
nodes.append(node)
event_dict[node] = []
for rsp in func('/noderange/{0}/events/hardware/log'.format(noderange)):
if 'error' in rsp:
sys.stderr.write(rsp['error'] + '\n')
@@ -107,6 +144,31 @@ for rsp in func('/noderange/{0}/events/hardware/log'.format(noderange)):
sys.stderr.write('{0}: {1}\n'.format(node, thisdata['error']))
exitcode |= 1
if 'events' in thisdata:
evtdata = thisdata['events']
for evt in evtdata:
print('{0}: {1}'.format(node, format_event(evt)))
evtdata = thisdata['events']
if options.lines:
event_dict[node].extend(evtdata)
else:
for evt in evtdata:
if options.timeframe:
# check if line is in timeframe
if 'timestamp' in evt and evt['timestamp'] is not None:
display = dt.strptime(evt['timestamp'], '%Y-%m-%dT%H:%M:%S')
if display > timeframe:
print('{0}: {1}'.format(node, format_event(evt)))
else:
print('{0}: {1}'.format(node, format_event(evt)))
if options.lines:
for node in nodes:
evtdata_list = event_dict[node]
if len(evtdata_list) != 0:
if len(evtdata_list) > options.lines:
evtdata_list = evtdata_list[-abs(options.lines):]
for evt in evtdata_list:
if options.timeframe:
if 'timestamp' in evt and evt['timestamp'] is not None:
display = dt.strptime(evt['timestamp'], '%Y-%m-%dT%H:%M:%S')
if display > timeframe:
print('{0}: {1}'.format(node, format_event(evt)))
else:
print('{0}: {1}'.format(node, format_event(evt)))
+46 -10
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2016-2017 Lenovo
@@ -56,23 +56,29 @@ components = ['all']
argparser = optparse.OptionParser(
usage="Usage: "
"%prog <noderange> [list][update [--backup <file>]]|[<components>]")
"%prog <noderange> [list][updatestatus][update [--backup <file>]]|[<components>]")
argparser.add_option('-b', '--backup', action='store_true',
help='Target a backup bank rather than primary')
argparser.add_option('-p', '--parameterfile', type='string',
help='When updating, use the specified parameter file')
argparser.add_option('-m', '--maxnodes', type='int',
help='When updating, prompt if more than the specified '
'number of servers will be affected')
(options, args) = argparser.parse_args()
upfile = None
querystatus = False
try:
noderange = args[0]
if len(args) > 1:
if args[1] == 'update':
upfile = args[2]
else:
comps = []
if args[1] == 'list':
comps = args[2:]
elif args[1] == 'updatestatus':
querystatus = True
else:
comps = args[1:]
components = []
@@ -108,13 +114,30 @@ def update_firmware(session, filename):
upargs = {'filename': filename}
if options.backup:
upargs['bank'] = 'backup'
if options.parameterfile:
with open(options.parameterfile, 'rb') as pf:
pfdata = pf.read()
upargs['parameterdata'] = pfdata
noderrs = {}
if session.unixdomain:
of = open(filename, 'rb')
try:
session.add_file(filename, of.fileno(), 'rb')
except Exception:
pass
filesbynode = {}
for exp in session.create('/noderange/{0}/attributes/expression'.format(noderange),
{'expression': filename}):
if 'error' in exp:
sys.stderr.write(exp['error'] + '\n')
exitcode |= exp.get('errorcode', 1)
ex = exp.get('databynode', ())
for node in ex:
filesbynode[node] = ex[node]['value']
if not isinstance(filesbynode[node], bytes) and not isinstance(filesbynode[node], str):
filesbynode[node] = filesbynode[node].encode('utf-8')
for node in filesbynode:
endfilename = filesbynode[node]
of = open(endfilename, 'rb')
try:
session.add_file(endfilename, of.fileno(), 'rb')
except Exception:
pass
for res in session.create(resource, upargs):
if 'created' not in res:
for nodename in res.get('databynode', ()):
@@ -149,9 +172,13 @@ def show_firmware(session):
firmware_shown = False
nodes_matched = False
for component in components:
category = 'all'
if component in ('adapters', 'disks', 'misc', 'core'):
category = component
component = 'all'
for res in session.read(
'/noderange/{0}/inventory/firmware/all/{1}'.format(
noderange, component)):
'/noderange/{0}/inventory/firmware/{2}/{1}'.format(
noderange, component, category)):
nodes_matched = True
exitcode |= client.printerror(res)
if 'databynode' not in res:
@@ -171,7 +198,16 @@ def show_firmware(session):
try:
session = client.Command()
if upfile is None:
if querystatus:
for res in session.read(
'/noderange/{0}/inventory/firmware/updatestatus'.format(noderange)):
for node in res.get('databynode', {}):
currstat = res['databynode'][node].get('status', None)
if currstat:
print('{}: {}'.format(node, currstat))
else:
print(repr(res))
elif upfile is None:
show_firmware(session)
else:
update_firmware(session, upfile)
+3 -1
View File
@@ -60,10 +60,12 @@ nodetype="nodegroups"
try:
nodegroups = args[0]
client.check_globbing(nodegroups)
nodelist = '/{0}/{1}/'.format(nodetype,nodegroups)
except IndexError:
argparser.print_help()
sys.exit(1)
nodelist = '/nodegroups/'
client.check_globbing(nodegroups)
session = client.Command()
exitcode = 0
+4 -4
View File
@@ -84,13 +84,13 @@ def main():
healthexplanations[node] = []
for sensor in health[node]['sensors']:
explanation = sensor['name'] + ':'
if sensor['value'] is not None:
if sensor.get('value', None) is not None:
explanation += str(sensor['value'])
if sensor['units'] is not None:
if sensor.get('units', None) is not None:
explanation += sensor['units']
if sensor['states']:
if sensor.get('states', None):
explanation += ','
if sensor['states']:
if sensor.get('states', None):
explanation += ','.join(sensor['states'])
healthexplanations[node].append(explanation)
if node in healthbynode and node in healthexplanations:
+42 -7
View File
@@ -49,23 +49,32 @@ def pretty(text):
def print_mem_info(node, prefix, meminfo):
memdescfmt = '{0}GB PC'
if meminfo['memory_type'] == 'DDR3 SDRAM':
if meminfo['memory_type'] is None:
memdescfmt = '{0}GB '
elif meminfo['memory_type'] == 'DDR3 SDRAM':
memdescfmt += '3-{1} '
elif 'DDR4' in meminfo['memory_type']:
memdescfmt += '4-{1} '
elif 'DDR5' in meminfo['memory_type']:
memdescfmt += '5-{1} '
elif 'DCPMM' in meminfo['memory_type']:
memdescfmt = '{0}GB {1} '
meminfo['module_type'] = 'DCPMM'
elif meminfo['memory_type'] == 'HBM':
memdescfmt = '{0}GB HBM '
else:
print('{0}: {1}: Unrecognized Memory'.format(node, prefix))
return
if meminfo.get('ecc', False):
memdescfmt += 'ECC '
capacity = meminfo['capacity_mb'] / 1024
modtype = meminfo.get('module_type', None)
if modtype:
memdescfmt += modtype
memdesc = memdescfmt.format(capacity, meminfo['speed'])
if meminfo.get('capacity_mb', None):
capacity = meminfo['capacity_mb'] // 1024
memdesc = memdescfmt.format(capacity, meminfo['speed'])
else:
memdesc = 'Unspecified Module'
print('{0}: {1} description: {2}'.format(node, prefix, memdesc))
print('{0}: {1} manufacturer: {2}'.format(
node, prefix, meminfo['manufacturer']))
@@ -99,6 +108,7 @@ usedprefixes = set([])
argparser = optparse.OptionParser(
usage="Usage: %prog <noderange> [serial|model|uuid|mac]")
argparser.add_option('-j', '--json', action='store_true', help='Output JSON')
argparser.add_option('-s', '--store', action='store_true', help='Store serial, model, and uuid into id.serial, id.model, and id.uuid')
(options, args) = argparser.parse_args()
try:
noderange = args[0]
@@ -126,17 +136,36 @@ if len(args) > 1:
try:
if options.json:
databynode = {}
if options.store and len(args) <= 1:
url = '/noderange/{0}/inventory/hardware/all/system'
pushattribs = {}
session = client.Command()
for res in session.read(url.format(noderange)):
printerror(res)
if 'databynode' not in res:
continue
for node in res['databynode']:
if options.store and node not in pushattribs:
pushattribs[node] = {}
printerror(res['databynode'][node], node)
if 'inventory' not in res['databynode'][node]:
continue
for inv in res['databynode'][node]['inventory']:
prefix = inv['name']
if options.store and prefix == 'System':
currinfo = inv.get('information', {})
curruuid = currinfo.get('UUID', '')
if curruuid:
curruuid = curruuid.lower()
pushattribs[node]['id.uuid'] = curruuid
currserial = currinfo.get('Serial Number', '')
if currserial:
currserial = currserial.strip()
pushattribs[node]['id.serial'] = currserial
currmodelnum = currinfo.get('Model', '')
if currmodelnum:
currmodelnum = currmodelnum.strip()
pushattribs[node]['id.model'] = currmodelnum
idx = 2
while (node, prefix) in usedprefixes:
prefix = '{0} {1}'.format(inv['name'], idx)
@@ -148,7 +177,7 @@ try:
if node not in databynode:
databynode[node] = {}
databynode[node][prefix] = inv
else:
elif not options.store:
print('{0}: {1}: Not Present'.format(node, prefix))
continue
info = inv['information']
@@ -179,12 +208,18 @@ try:
databynode[node] = {}
databynode[node][prefix] = inv
break
print(u'{0}: {1} {2}: {3}'.format(node, prefix,
pretty(datum),
info[datum]))
elif not options.store:
print(u'{0}: {1} {2}: {3}'.format(node, prefix,
pretty(datum),
info[datum]))
if options.json:
print(json.dumps(databynode, sort_keys=True, indent=4,
separators=(',', ': ')))
if pushattribs:
for node in pushattribs:
for rsp in session.update('/nodes/{0}/attributes/current'.format(node), pushattribs[node]):
if 'error' in rsp:
sys.stderr.write(rsp['error'] + '\n')
except KeyboardInterrupt:
print('')
sys.exit(exitcode)
+176
View File
@@ -0,0 +1,176 @@
#!/usr/libexec/platform-python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2017 Lenovo
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__author__ = 'tkucherera'
import optparse
import os
import signal
import sys
import subprocess
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
pass
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
if path.startswith('/opt'):
sys.path.append(path)
import confluent.client as client
argparser = optparse.OptionParser(
usage="Usage: %prog <start_node> -i <interface> <end_node> -e <eface>",
)
argparser.add_option('-i', '--interface', type='str',
help='interface to check path against for the start node')
argparser.add_option('-e', '--eface', type='str',
help='interface to check path against for the end node')
argparser.add_option('-c', '--cumulus', action="store_true", dest="cumulus",
help='return layer 2 route through cumulus switches only')
(options, args) = argparser.parse_args()
try:
start_node = args[0]
end_node = args[1]
interface = options.interface
eface = options.eface
except IndexError:
argparser.print_help()
sys.exit(1)
session = client.Command()
def get_neighbors(switch):
switch_neigbors = []
url = '/networking/neighbors/by-switch/{0}/by-peername/'.format(switch)
for neighbor in session.read(url):
try:
switch = neighbor['item']['href'].strip('/')
except:
continue
if switch in all_switches:
switch_neigbors.append(switch)
return switch_neigbors
def find_path(start, end, path=[]):
path = path + [start]
if start == end:
return path # If start and end are the same, return the path
for node in get_neighbors(start):
if node not in path:
new_path = find_path(node, end, path)
if new_path:
return new_path # If a path is found, return it
return None # If no path is found, return None
def is_cumulus(switch):
try:
read_attrib = subprocess.check_output(['nodeattrib', switch, 'hardwaremanagement.method'])
except subprocess.CalledProcessError:
return False
for attribs in read_attrib.decode('utf-8').split('\n'):
if len(attribs.split(':')) > 1:
attrib = attribs.split(':')
if attrib[2].strip() == 'affluent':
return True
else:
return False
else:
return False
def host_to_switch(node, interface=None):
# first check the the node config to see what switches are connected
# if host is in rhel can use nmstate package
if node in all_switches:
return [node]
switches = []
netarg = 'net.*.switch'
if interface:
netarg = 'net.{0}.switch'.format(interface)
try:
read_attrib = subprocess.check_output(['nodeattrib', node, netarg])
except subprocess.CalledProcessError:
return False
for attribs in read_attrib.decode('utf-8').split('\n'):
attrib = attribs.split(':')
try:
if ' net.mgt.switch' in attrib or attrib[2] == '':
continue
except IndexError:
continue
switch = attrib[2].strip()
if is_cumulus(switch) and options.cumulus:
switches.append(switch)
else:
switches.append(switch)
return switches
def path_between_nodes(start_switches, end_switches):
for start_switch in start_switches:
for end_switch in end_switches:
if start_switch == end_switch:
return [start_switch]
else:
path = find_path(start_switch, end_switch)
if path:
return path
else:
return 'No path found'
all_switches = []
for res in session.read('/networking/neighbors/by-switch/'):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
exitcode = 1
else:
switch = (res['item']['href'].replace('/', ''))
all_switches.append(switch)
end_nodeslist = []
nodelist = '/noderange/{0}/nodes/'.format(end_node)
for res in session.read(nodelist):
if 'error' in res:
sys.stderr.write(res['error'] + '\n')
exitcode = 1
else:
elem=(res['item']['href'].replace('/', ''))
end_nodeslist.append(elem)
start_switches = host_to_switch(start_node, interface)
for end_node in end_nodeslist:
if end_node:
end_switches = host_to_switch(end_node, eface)
if not end_switches:
print('Error: net.{0}.switch attribute is not valid')
continue
path = path_between_nodes(start_switches, end_switches)
print(f'{start_node} to {end_node}: {path}')
# TODO dont put switches that are connected through management interfaces.
+20 -6
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2019 Lenovo
@@ -65,16 +65,30 @@ client.check_globbing(noderange)
def install_license(session, filename):
global exitcode
resource = '/noderange/{0}/configuration/' \
'management_controller/licenses/'.format(noderange)
filename = os.path.abspath(filename)
instargs = {'filename': filename}
if session.unixdomain:
of = open(filename, 'rb')
try:
session.add_file(filename, of.fileno(), 'rb')
except Exception:
pass
filesbynode = {}
for exp in session.create('/noderange/{0}/attributes/expression'.format(noderange),
{'expression': filename}):
if 'error' in exp:
sys.stderr.write(exp['error'] + '\n')
exitcode |= exp.get('errorcode', 1)
ex = exp.get('databynode', ())
for node in ex:
filesbynode[node] = ex[node]['value']
if not isinstance(filesbynode[node], bytes) and not isinstance(filesbynode[node], str):
filesbynode[node] = filesbynode[node].encode('utf-8')
for node in filesbynode:
endfilename = filesbynode[node]
of = open(endfilename, 'rb')
try:
session.add_file(endfilename, of.fileno(), 'rb')
except Exception:
pass
for res in session.create(resource, instargs):
for node in res.get('databynode', []):
if 'error' in res['databynode'][node]:
+10 -3
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/libexec/platform-python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2015-2017 Lenovo
@@ -15,13 +15,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
__author__ = 'jjohnson2,alin37'
__author__ = 'jjohnson2,alin37,wgrzeda'
import optparse
import os
import signal
import sys
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except AttributeError:
@@ -39,9 +41,12 @@ def main():
" or: %prog [options] noderange <nodeattribute>...")
argparser.add_option('-b', '--blame', action='store_true',
help='Show information about how attributes inherited')
argparser.add_option('-d', '--delim', metavar="STRING", default = "\n",
help='Delimiter separating the values')
(options, args) = argparser.parse_args()
noderange=""
nodelist=""
list = []
try:
noderange = args[0]
nodelist = '/noderange/{0}/nodes/'.format(noderange)
@@ -61,7 +66,9 @@ def main():
sys.stderr.write(res['error'] + '\n')
exitcode = 1
else:
print(res['item']['href'].replace('/', ''))
elem=(res['item']['href'].replace('/', ''))
list.append(elem)
print(options.delim.join(list))
sys.exit(exitcode)
+25 -10
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2018 Lenovo
@@ -101,22 +101,37 @@ def detach_media(noderange, media):
def upload_media(noderange, media):
global exitcode
if not os.path.exists(media):
sys.stderr.write('Unable to locate requested file {0}\n'.format(
media))
sys.exit(404)
session = client.Command()
output = sq.ScreenPrinter(noderange, session)
filename = os.path.abspath(media)
resource = '/noderange/{0}/media/uploads/'.format(noderange)
filename = os.path.abspath(filename)
upargs = {'filename': filename}
noderrs = {}
if session.unixdomain:
of = open(filename, 'rb')
try:
session.add_file(filename, of.fileno(), 'rb')
except Exception:
pass
filesbynode = {}
for exp in session.create('/noderange/{0}/attributes/expression'.format(noderange),
{'expression': filename}):
if 'error' in exp:
sys.stderr.write(exp['error'] + '\n')
exitcode |= exp.get('errorcode', 1)
ex = exp.get('databynode', ())
for node in ex:
filesbynode[node] = ex[node]['value']
if not isinstance(filesbynode[node], bytes) and not isinstance(filesbynode[node], str):
filesbynode[node] = filesbynode[node].encode('utf-8')
for node in filesbynode:
endfilename = filesbynode[node]
if not os.path.exists(endfilename):
sys.stderr.write('Unable to locate requested file {0}\n'.format(
endfilename))
sys.exit(404)
of = open(endfilename, 'rb')
try:
session.add_file(endfilename, of.fileno(), 'rb')
except Exception:
pass
nodeurls = {}
for res in session.create(resource, upargs):
if 'created' not in res:
+30 -13
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2016-2017 Lenovo
@@ -42,8 +42,10 @@ def run():
usage="Usage: %prog [options] noderange")
argparser.add_option('-f', '-c', '--count', type='int', default=168,
help='Number of commands to run at a time')
argparser.add_option('-o', '--origname', action='store_true',
help='Use original nodename in print out even if substituted')
argparser.add_option('-s', '--substitutename',
help='Use a different name other than the nodename for ping')
help='Use a different name other than the nodename for ping, with {}, it is the entire name evaluated as an expression, otherwise it is used as a suffix')
# among other things, FD_SETSIZE limits. Besides, spawning too many
# processes can be unkind for the unaware on memory pressure and such...
(options, args) = argparser.parse_args()
@@ -56,6 +58,7 @@ def run():
currprocs = 0
all = set([])
poller = select.epoll()
pipedesc = {}
pendingexecs = deque()
exitcode = 0
@@ -83,19 +86,29 @@ def run():
cmdv = ['ping', '-c', '1', '-W', '1', pingnode]
if currprocs < concurrentprocs:
currprocs += 1
run_cmdv(node, cmdv, all, pipedesc)
if options.origname:
run_cmdv(node, cmdv, all, poller, pipedesc)
else:
run_cmdv(pingnode, cmdv, all, poller, pipedesc)
else:
pendingexecs.append((node, cmdv))
if options.origname:
pendingexecs.append((node, cmdv))
else:
pendingexecs.append((pingnode, cmdv))
if not all or exitcode:
sys.exit(exitcode)
rdy, _, _ = select.select(all, [], [], 10)
rdy = poller.poll(10)
while all:
pernodeout = {}
for r in rdy:
r = r[0]
desc = pipedesc[r]
r = desc['file']
node = desc['node']
data = True
while data and select.select([r], [], [], 0)[0]:
singlepoller = select.epoll()
singlepoller.register(r, select.EPOLLIN)
while data and singlepoller.poll(0):
data = r.readline()
if not data:
pop = desc['popen']
@@ -103,6 +116,7 @@ def run():
if ret is not None:
exitcode = exitcode | ret
all.discard(r)
poller.unregister(r)
r.close()
if desc['type'] == 'stdout':
if ret:
@@ -111,7 +125,8 @@ def run():
print('{0}: ping'.format(node))
if pendingexecs:
node, cmdv = pendingexecs.popleft()
run_cmdv(node, cmdv, all, pipedesc)
run_cmdv(node, cmdv, all, poller, pipedesc)
singlepoller.close()
for node in sortutil.natural_sort(pernodeout):
for line in pernodeout[node]:
line = client.stringify(line)
@@ -121,19 +136,21 @@ def run():
sys.stdout.write('{0}: {1}'.format(node, line))
sys.stdout.flush()
if all:
rdy, _, _ = select.select(all, [], [], 10)
rdy = poller.poll(10)
sys.exit(exitcode)
def run_cmdv(node, cmdv, all, pipedesc):
def run_cmdv(node, cmdv, all, poller, pipedesc):
nopen = subprocess.Popen(
cmdv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pipedesc[nopen.stdout] = {'node': node, 'popen': nopen,
'type': 'stdout'}
pipedesc[nopen.stderr] = {'node': node, 'popen': nopen,
'type': 'stderr'}
pipedesc[nopen.stdout.fileno()] = {'node': node, 'popen': nopen,
'type': 'stdout', 'file': nopen.stdout}
pipedesc[nopen.stderr.fileno()] = {'node': node, 'popen': nopen,
'type': 'stderr', 'file': nopen.stderr}
all.add(nopen.stdout)
poller.register(nopen.stdout, select.EPOLLIN)
all.add(nopen.stderr)
poller.register(nopen.stderr, select.EPOLLIN)
if __name__ == '__main__':
+1 -1
View File
@@ -55,7 +55,7 @@ if len(args) > 1:
if setstate == 'softoff':
setstate = 'shutdown'
if setstate not in (None, 'on', 'off', 'shutdown', 'boot', 'reset', 'pdu_status', 'pdu_stat', 'pdu_on', 'pdu_off'):
if setstate not in (None, 'on', 'off', 'shutdown', 'boot', 'reset', 'pdu_status', 'pdu_stat', 'pdu_on', 'pdu_off', 'status', 'stat', 'state'):
argparser.print_help()
sys.exit(1)
session = client.Command()
+18 -1
View File
@@ -46,6 +46,10 @@ def run():
help='Specify a maximum number of '
'nodes to run rsync to, '
'prompting if over the threshold')
argparser.add_option('-l', '--loginname', type='str',
help='Username to use when connecting, defaults to current user.')
argparser.add_option('-s', '--substitutename',
help='Use a different name other than the nodename for rsync')
argparser.add_option('-f', '-c', '--count', type='int', default=168,
help='Number of nodes to concurrently rsync')
# among other things, FD_SETSIZE limits. Besides, spawning too many
@@ -61,7 +65,20 @@ def run():
c = client.Command()
cmdstr = ' '.join(args[:-1])
cmdstr = 'rsync -av --info=progress2 ' + cmdstr
cmdstr += ' {node}:' + targpath
targname = options.substitutename
if targname and '{' in targname:
targname = targname + ':'
elif targname:
targname = '{node}' + targname + ':'
else:
targname = '{node}:'
if options.loginname:
cmdstr += ' {}@'.format(options.loginname) + targname + targpath
else:
cmdstr += ' {}'.format(targname) + targpath
currprocs = 0
all = set([])
+24 -13
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2016-2017 Lenovo
@@ -35,9 +35,12 @@ if path.startswith('/opt'):
import confluent.client as client
import confluent.sortutil as sortutil
devnull = None
def run():
global devnull
devnull = open(os.devnull, 'rb')
argparser = optparse.OptionParser(
usage="Usage: %prog [options] <noderange> <command expression>",
epilog="Expressions are the same as in attributes, e.g. "
@@ -64,6 +67,7 @@ def run():
currprocs = 0
all = set([])
poller = select.epoll()
pipedesc = {}
pendingexecs = deque()
exitcode = 0
@@ -81,19 +85,23 @@ def run():
cmdv = shlex.split(cmd)
if currprocs < concurrentprocs:
currprocs += 1
run_cmdv(node, cmdv, all, pipedesc)
run_cmdv(node, cmdv, all, poller, pipedesc)
else:
pendingexecs.append((node, cmdv))
if not all or exitcode:
sys.exit(exitcode)
rdy, _, _ = select.select(all, [], [], 10)
rdy = poller.poll(10)
while all:
pernodeout = {}
for r in rdy:
r = r[0]
desc = pipedesc[r]
r = desc['file']
node = desc['node']
data = True
while data and select.select([r], [], [], 0)[0]:
singlepoller = select.epoll()
singlepoller.register(r, select.EPOLLIN)
while data and singlepoller.poll(0):
data = r.readline()
if data:
if desc['type'] == 'stdout':
@@ -113,10 +121,12 @@ def run():
if ret is not None:
exitcode = exitcode | ret
all.discard(r)
poller.unregister(r)
r.close()
if desc['type'] == 'stdout' and pendingexecs:
node, cmdv = pendingexecs.popleft()
run_cmdv(node, cmdv, all, pipedesc)
run_cmdv(node, cmdv, all, poller, pipedesc)
singlepoller.close()
for node in sortutil.natural_sort(pernodeout):
for line in pernodeout[node]:
line = client.stringify(line)
@@ -126,26 +136,27 @@ def run():
sys.stdout.write('{0}: {1}'.format(node, line))
sys.stdout.flush()
if all:
rdy, _, _ = select.select(all, [], [], 10)
rdy = poller.poll(10)
sys.exit(exitcode)
def run_cmdv(node, cmdv, all, pipedesc):
def run_cmdv(node, cmdv, all, poller, pipedesc):
try:
nopen = subprocess.Popen(
cmdv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
cmdv, stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError as e:
if e.errno == 2:
sys.stderr.write('{0}: Unable to find local executable file "{1}"'.format(node, cmdv[0]))
return
raise
pipedesc[nopen.stdout] = {'node': node, 'popen': nopen,
'type': 'stdout'}
pipedesc[nopen.stderr] = {'node': node, 'popen': nopen,
'type': 'stderr'}
pipedesc[nopen.stdout.fileno()] = {'node': node, 'popen': nopen,
'type': 'stdout', 'file': nopen.stdout}
pipedesc[nopen.stderr.fileno()] = {'node': node, 'popen': nopen,
'type': 'stderr', 'file': nopen.stderr}
all.add(nopen.stdout)
poller.register(nopen.stdout, select.EPOLLIN)
all.add(nopen.stderr)
poller.register(nopen.stderr, select.EPOLLIN)
if __name__ == '__main__':
run()
+15 -7
View File
@@ -37,6 +37,12 @@ class hybridcsv(csv.excel):
lineterminator = '\n'
def floatformat(num):
fm = u'{:.5f}'.format(num).rstrip('0')
if fm[-1:] == u'.':
return fm + u'0'
return fm
csv.register_dialect('hybrid', hybridcsv)
import confluent.client as client
@@ -61,7 +67,7 @@ argparser.add_option('-n', '--numreadings', type='int',
argparser.add_option('-c', '--csv', action='store_true',
help='Output in CSV format')
argparser.add_option('-s', '--skipnumberless', action='store_true',
help='Output in CSV format')
help='Do not show non-numeric sensors')
(options, args) = argparser.parse_args()
repeatmode = False
if options.interval:
@@ -117,7 +123,7 @@ def sensorpass(showout=True, appendtime=False):
if 'sensors' not in reading[node]:
continue
for sensedata in reading[node]['sensors']:
if sensedata['value'] is None and options.skipnumberless:
if sensedata.get('value', None) is None and options.skipnumberless:
continue
for redundant_state in ('Non-Critical', 'Critical'):
try:
@@ -128,17 +134,17 @@ def sensorpass(showout=True, appendtime=False):
resultdata[node][sensedata['name']] = sensedata
sensorname = sensedata['name']
sensorheaders[sensorname] = sensorname
if sensedata['units'] not in (None, u''):
if sensedata.get('units', None) not in (None, u''):
sensorheaders[sensorname] += u' ({0})'.format(
sensedata['units'])
if showout:
if sensedata['value'] is None:
if sensedata.get('value', None) is None:
showval = ''
elif isinstance(sensedata['value'], float):
showval = u' {0:.5f} '.format(sensedata['value'])
showval = u' {0} '.format(floatformat(sensedata['value']))
else:
showval = u' {0} '.format(sensedata['value'])
if sensedata['units'] not in (None, u''):
showval = u' {0} '.format(sensedata.get('value', ''))
if sensedata.get('units', None) not in (None, u''):
showval += sensedata['units']
if sensedata.get('health', 'ok') != 'ok':
datadescription = [sensedata['health']]
@@ -191,6 +197,8 @@ def format_csv(csvwriter, orderedsensors, resdata, showtime=True):
datum = ','.join([datum, healthstates])
else:
datum = healthstates
if isinstance(datum, float):
datum = floatformat(datum)
rowdata.append(datum)
except KeyError:
rowdata.append('N/A')
+1 -1
View File
@@ -32,7 +32,7 @@ if path.startswith('/opt'):
import confluent.client as client
argparser = optparse.OptionParser(
usage='Usage: %prog [options] <noderange> [default|cd|network|setup|hd|usb|floppy]')
usage='Usage: %prog [options] <noderange> [default|cd|network|http|setup|hd|usb|floppy]')
argparser.add_option('-b', '--bios', dest='biosmode',
action='store_true', default=False,
help='Request BIOS style boot (rather than UEFI)')
+24 -14
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python3
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2016-2017 Lenovo
@@ -34,10 +34,11 @@ if path.startswith('/opt'):
import confluent.client as client
import confluent.sortutil as sortutil
devnull = None
def run():
global devnull
devnull = open(os.devnull, 'rb')
argparser = optparse.OptionParser(
usage="Usage: %prog [options] noderange commandexpression",
epilog="Expressions are the same as in attributes, e.g. "
@@ -108,6 +109,7 @@ def run():
ex = exp.get('databynode', ())
for node in ex:
cmdparms.append((node, ex[node]['value']))
poller = select.epoll()
for node, cmd in cmdparms:
sshnode = nodemap.get(node, node)
if not isinstance(cmd, str) and not isinstance(cmd, bytes):
@@ -120,19 +122,23 @@ def run():
cmdv += [sshnode, cmd]
if currprocs < concurrentprocs:
currprocs += 1
run_cmdv(node, cmdv, all, pipedesc)
run_cmdv(node, cmdv, all, poller, pipedesc)
else:
pendingexecs.append((node, cmdv))
if not all or exitcode:
sys.exit(exitcode)
rdy, _, _ = select.select(all, [], [], 10)
rdy = poller.poll(10)
while all:
pernodeout = {}
for r in rdy:
r = r[0]
desc = pipedesc[r]
r = desc['file']
node = desc['node']
data = True
while data and select.select([r], [], [], 0)[0]:
singlepoller = select.epoll()
singlepoller.register(r, select.EPOLLIN)
while data and singlepoller.poll(0):
data = r.readline()
if data:
if desc['type'] == 'stdout':
@@ -152,10 +158,12 @@ def run():
if ret is not None:
exitcode = exitcode | ret
all.discard(r)
poller.unregister(r)
r.close()
if desc['type'] == 'stdout' and pendingexecs:
node, cmdv = pendingexecs.popleft()
run_cmdv(node, cmdv, all, pipedesc)
run_cmdv(node, cmdv, all, poller, pipedesc)
singlepoller.close()
for node in sortutil.natural_sort(pernodeout):
for line in pernodeout[node]:
line = client.stringify(line)
@@ -166,19 +174,21 @@ def run():
sys.stdout.write('{0}: {1}'.format(node, line))
sys.stdout.flush()
if all:
rdy, _, _ = select.select(all, [], [], 10)
rdy = poller.poll(10)
sys.exit(exitcode)
def run_cmdv(node, cmdv, all, pipedesc):
def run_cmdv(node, cmdv, all, poller, pipedesc):
nopen = subprocess.Popen(
cmdv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pipedesc[nopen.stdout] = {'node': node, 'popen': nopen,
'type': 'stdout'}
pipedesc[nopen.stderr] = {'node': node, 'popen': nopen,
'type': 'stderr'}
cmdv, stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pipedesc[nopen.stdout.fileno()] = {'node': node, 'popen': nopen,
'type': 'stdout', 'file': nopen.stdout}
pipedesc[nopen.stderr.fileno()] = {'node': node, 'popen': nopen,
'type': 'stderr', 'file': nopen.stderr}
all.add(nopen.stdout)
all.add(nopen.stderr)
poller.register(nopen.stdout, select.EPOLLIN)
poller.register(nopen.stderr, select.EPOLLIN)
if __name__ == '__main__':
+39 -9
View File
@@ -16,13 +16,11 @@
# limitations under the License.
import argparse
import base64
import csv
import fcntl
import io
import numpy as np
import os
import subprocess
import numpy as np
import sys
try:
@@ -35,7 +33,31 @@ except ImportError:
pass
def plot(gui, output, plotdata, bins):
def iterm_draw(data):
databuf = data.getbuffer()
datalen = len(databuf)
data = base64.b64encode(databuf).decode('utf8')
sys.stdout.write(
'\x1b]1337;File=inline=1;size={}:'.format(datalen))
sys.stdout.write(data)
sys.stdout.write('\a')
sys.stdout.write('\n')
sys.stdout.flush()
def kitty_draw(data):
data = base64.b64encode(data.getbuffer())
while data:
chunk, data = data[:4096], data[4096:]
m = 1 if data else 0
sys.stdout.write('\x1b_Ga=T,f=100,m={};'.format(m))
sys.stdout.write(chunk.decode('utf8'))
sys.stdout.write('\x1b\\')
sys.stdout.flush()
sys.stdout.write('\n')
def plot(gui, output, plotdata, bins, fmt):
import matplotlib as mpl
if gui and mpl.get_backend() == 'agg':
sys.stderr.write('Error: No GUI backend available and -g specified!\n')
@@ -51,8 +73,15 @@ def plot(gui, output, plotdata, bins):
tdata = io.BytesIO()
plt.savefig(tdata)
if not gui and not output:
writer = DumbWriter()
writer.draw(tdata)
if fmt == 'environment':
fmt = os.environ.get('CONFLUENT_IMAGE_PROTOCOL', 'kitty')
if fmt == 'sixel':
writer = DumbWriter()
writer.draw(tdata)
elif fmt == 'kitty':
kitty_draw(tdata)
elif fmt == 'iterm':
iterm_draw(tdata)
return n, bins
def textplot(plotdata, bins):
@@ -81,7 +110,8 @@ histogram = False
aparser = argparse.ArgumentParser(description='Quick access to common statistics')
aparser.add_argument('-c', type=int, default=0, help='Column number to analyze (default is last column)')
aparser.add_argument('-d', default=None, help='Value used to separate columns')
aparser.add_argument('-x', default=False, action='store_true', help='Output histogram in sixel format')
aparser.add_argument('-x', default=False, action='store_true', help='Output histogram in graphical format')
aparser.add_argument('-f', default='environment', help='Format for histogram output (sixel/iterm/kitty)')
aparser.add_argument('-s', default=0, help='Number of header lines to skip before processing')
aparser.add_argument('-g', default=False, action='store_true', help='Open histogram in separate graphical window')
aparser.add_argument('-o', default=None, help='Output histogram to the specified filename in PNG format')
@@ -138,7 +168,7 @@ while data:
data = list(csv.reader([data], delimiter=delimiter))[0]
n = None
if args.g or args.o or args.x:
n, bins = plot(args.g, args.o, plotdata, bins=args.b)
n, bins = plot(args.g, args.o, plotdata, bins=args.b, fmt=args.f)
if args.t:
n, bins = textplot(plotdata, bins=args.b)
print('Samples: {5} Min: {3} Median: {0} Mean: {1} Max: {4} StandardDeviation: {2} Sum: {6}'.format(np.median(plotdata), np.mean(plotdata), np.std(plotdata), np.min(plotdata), np.max(plotdata), len(plotdata), np.sum(plotdata)))
+22 -6
View File
@@ -57,7 +57,7 @@ def stringify(instr):
# Normalize unicode and bytes to 'str', correcting for
# current python version
if isinstance(instr, bytes) and not isinstance(instr, str):
return instr.decode('utf-8')
return instr.decode('utf-8', errors='replace')
elif not isinstance(instr, bytes) and not isinstance(instr, str):
return instr.encode('utf-8')
return instr
@@ -391,8 +391,13 @@ class Command(object):
cacert = None
certreqs = ssl.CERT_NONE
knownhosts = True
self.connection = ssl.wrap_socket(self.connection, ca_certs=cacert,
cert_reqs=certreqs)
tlsctx = ssl.create_default_context()
if certreqs == ssl.CERT_NONE:
tlsctx.check_hostname = False
tlsctx.verify_mode = certreqs
if cacert:
tlsctx.load_verify_locations(cacert)
self.connection = tlsctx.wrap_socket(self.connection, server_hostname=server)
if knownhosts:
certdata = self.connection.getpeercert(binary_form=True)
fingerprint = 'sha512$' + hashlib.sha512(certdata).hexdigest()
@@ -464,8 +469,8 @@ def printattributes(session, requestargs, showtype, nodetype, noderange, options
def _sort_attrib(k):
if isinstance(k[1], dict) and k[1].get('sortid', None) is not None:
return k[1]['sortid']
return k[0]
return sortutil.naturalize_string('{}'.format(k[1]['sortid']))
return sortutil.naturalize_string(k[0])
def print_attrib_path(path, session, requestargs, options, rename=None, attrprefix=None):
exitcode = 0
@@ -595,7 +600,7 @@ def print_attrib_path(path, session, requestargs, options, rename=None, attrpref
else:
printmissing.add(attr)
for missing in printmissing:
sys.stderr.write('Error: {0} not a valid attribute\n'.format(attr))
sys.stderr.write('Error: {0} not a valid attribute\n'.format(missing))
return exitcode
@@ -668,6 +673,9 @@ def updateattrib(session, updateargs, nodetype, noderange, options, dictassign=N
for attrib in updateargs[1:]:
keydata[attrib] = None
for res in session.update(targpath, keydata):
for node in res.get('databynode', {}):
for warnmsg in res['databynode'][node].get('_warnings', []):
sys.stderr.write('Warning: ' + warnmsg + '\n')
if 'error' in res:
if 'errorcode' in res:
exitcode = res['errorcode']
@@ -702,6 +710,14 @@ def updateattrib(session, updateargs, nodetype, noderange, options, dictassign=N
noderange, 'attributes/all', dictassign[key], key)
else:
if "=" in updateargs[1]:
update_ready = True
for arg in updateargs[1:]:
if not '=' in arg:
update_ready = False
exitcode = 1
if not update_ready:
sys.stderr.write('Error: {0} Can not set and read at the same time!\n'.format(str(updateargs[1:])))
sys.exit(exitcode)
try:
for val in updateargs[1:]:
val = val.split('=', 1)
+49 -2
View File
@@ -282,14 +282,61 @@ def _replay_to_console(txtfile, binfile):
def replay_to_console(txtfile):
if os.path.exists(txtfile + '.cbl'):
binfile = txtfile + '.cbl'
elif '.' not in txtfile:
if '/' not in txtfile:
txtfile = os.getcwd() + '/' + txtfile
sys.stderr.write('Unable to locate cbl file: "{0}"\n'.format(txtfile + '.cbl'))
sys.exit(1)
else:
fileparts = txtfile.split('.')
prefix = '.'.join(fileparts[:-1])
binfile = prefix + '.cbl.' + fileparts[-1]
if not os.path.exists(binfile):
sys.stderr.write('Unable to locate cbl file\n')
sys.stderr.write('Unable to locate cbl file: "{0}"\n'.format(binfile))
sys.exit(1)
_replay_to_console(txtfile, binfile)
def dump_to_console(txtfile):
if os.path.exists(txtfile + '.cbl'):
binfile = txtfile + '.cbl'
elif '.' not in txtfile:
if '/' not in txtfile:
txtfile = os.getcwd() + '/' + txtfile
sys.stderr.write('Unable to locate cbl file: "{0}"\n'.format(txtfile + '.cbl'))
sys.exit(1)
else:
fileparts = txtfile.split('.')
prefix = '.'.join(fileparts[:-1])
binfile = prefix + '.cbl.' + fileparts[-1]
if not os.path.exists(binfile):
sys.stderr.write('Unable to locate cbl file: "{0}"\n'.format(binfile))
sys.exit(1)
replay = LogReplay(txtfile, binfile)
quitit = False
writeout('\x1b[2J\x1b[;H')
prepend = ''
try:
while not quitit:
newdata, delay = replay.get_output(False)
if newdata:
if prepend:
newdata = prepend + newdata
prepend = b''
writeout(newdata.replace(b'\r\n', '\r\n[ {0} ] '.format(time.strftime('%m/%d %H:%M:%S', time.localtime(replay.laststamp))).encode('utf8')))
newdata = ''
try:
if hasattr(sys.stdout, 'buffer'):
sys.stdout.buffer.flush()
else:
sys.stdout.flush()
except IOError:
pass
else:
break
except Exception:
writeout('\x1b[m\x1b[?25h\n')
raise
writeout('\x1b[m\x1b[?25h\n')
if __name__ == '__main__':
replay_to_console(sys.argv[1])
replay_to_console(sys.argv[1])
+48 -16
View File
@@ -18,8 +18,9 @@ import struct
import termios
def get_screengeom():
return struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,
b'....'))
# returns height in cells, width in cells, width in pixels, height in pixels
return struct.unpack('hhhh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,
b'........'))
class ScreenPrinter(object):
def __init__(self, noderange, client, textlen=4):
@@ -29,6 +30,9 @@ class ScreenPrinter(object):
self.client = client
self.nodeoutput = {}
self.nodelist = []
self.nodepos = {}
self.lastrows = 0
self.fieldchanged = False
maxlen = 0
for ans in self.client.read('/noderange/{0}/nodes/'.format(noderange)):
if 'error' in ans:
@@ -50,16 +54,19 @@ class ScreenPrinter(object):
if len(text) >= self.textlen:
self.textlen = len(text) + 1
self.fieldwidth = self.textlen + self.nodenamelen + 1
self.drawscreen()
self.fieldchanged = True
self.drawscreen(node)
def drawscreen(self):
def drawscreen(self, node=None):
if self.squeeze:
currheight, currwidth = get_screengeom()
currheight -= 1
currheight, currwidth, _, _ = get_screengeom()
currheight -= 2
if currheight < 1:
currheight = 1
numfields = currwidth // self.fieldwidth
fieldformat = '{{0:>{0}}}:{{1:{1}}}'.format(self.nodenamelen,
self.textlen)
sys.stdout.write('\x1b[2J\x1b[;H') # clear screen
#sys.stdout.write('\x1b[2J\x1b[;H') # clear screen
if len(self.nodelist) < (numfields * currheight):
numfields = len(self.nodelist) // currheight + 1
else:
@@ -67,16 +74,40 @@ class ScreenPrinter(object):
fieldformat = '{0}: {1}'
if self.squeeze:
columns = [self.nodelist[x:x+currheight] for x in range(0, len(self.nodelist), currheight)]
for currow in range(0, len(columns[0])):
for col in columns:
try:
node = col[currow]
sys.stdout.write(fieldformat.format(node, self.nodeoutput[node]))
except IndexError:
break
sys.stdout.write('\n')
if self.lastrows:
sys.stdout.write('\x1b[{0}A'.format(self.lastrows))
if node and self.lastrows == len(columns[0]) and not self.fieldchanged:
targline, targcol = self.nodepos[node]
if targline:
sys.stdout.write('\x1b[{0}B'.format(targline))
if targcol:
sys.stdout.write('\x1b[{0}C'.format(targcol))
sys.stdout.write(fieldformat.format(node, self.nodeoutput[node]))
sys.stdout.write('\r\x1b[{0}B'.format(self.lastrows - targline))
else:
self.lastrows = 0
self.fieldchanged = False
column = 0
for currow in range(0, len(columns[0])):
sys.stdout.write('\x1b[2K')
for col in columns:
try:
node = col[currow]
self.nodepos[node] = (currow, column)
sys.stdout.write(fieldformat.format(node, self.nodeoutput[node]))
column += len(fieldformat.format(node, self.nodeoutput[node]))
except IndexError:
break
sys.stdout.write('\n')
column = 0
self.lastrows += 1
sys.stdout.write('\x1b[J')
else:
for node in self.nodelist:
if node:
nodes = [node]
else:
nodes = self.nodelist
for node in nodes:
sys.stdout.write(fieldformat.format(node, self.nodeoutput[node]))
sys.stdout.write('\n')
sys.stdout.flush()
@@ -90,6 +121,7 @@ if __name__ == '__main__':
c = client.Command()
p = ScreenPrinter('d1-d12', c)
p.set_output('d3', 'Upload: 67%')
p.set_output('d7', 'Upload: 67%')
+15 -4
View File
@@ -98,17 +98,24 @@ class GroupedData(object):
self.byoutput = {}
self.header = {}
self.client = confluentconnection
self.detectedpad = None
def generate_byoutput(self):
self.byoutput = {}
thepad = self.detectedpad if self.detectedpad else ''
for n in self.bynode:
output = '\n'.join(self.bynode[n])
output = ''
for ln in self.bynode[n]:
output += ln.replace(thepad, '', 1) + '\n'
if output not in self.byoutput:
self.byoutput[output] = set([n])
else:
self.byoutput[output].add(n)
def add_line(self, node, line):
wspc = re.search(r'^\s*', line).group()
if self.detectedpad is None or len(wspc) < len(self.detectedpad):
self.detectedpad = wspc
if node not in self.bynode:
self.bynode[node] = [line]
else:
@@ -164,7 +171,9 @@ class GroupedData(object):
self.byoutput[outdata])))
currout += '\n====================================\n'
currout += outdata
currout += '\n\n'
if currout[-1] != '\n':
currout += '\n'
currout += '\n'
output.write(currout)
output.flush()
@@ -204,7 +213,9 @@ class GroupedData(object):
else:
currout += '\n'.join(colordiff(modaloutput.split('\n'),
outdata.split('\n')))
currout += '\n\n'
if currout[-1] != '\n':
currout += '\n'
currout += '\n'
if reverse:
revoutput.append(currout)
else:
@@ -219,4 +230,4 @@ if __name__ == '__main__':
if not line:
continue
groupoutput.add_line(*line.split(': ', 1))
groupoutput.print_deviants()
groupoutput.print_deviants()
+12 -4
View File
@@ -19,8 +19,12 @@ import array
import ctypes
import ctypes.util
import confluent.tlv as tlv
import eventlet.green.socket as socket
import eventlet.green.select as select
try:
import eventlet.green.socket as socket
import eventlet.green.select as select
except ImportError:
import socket
import select
from datetime import datetime
import json
import os
@@ -240,8 +244,12 @@ def recv(handle):
cdata = cmsgarr[CMSG_LEN(0).value:]
data = rawbuffer[:i]
if cmsg.cmsg_level == socket.SOL_SOCKET and cmsg.cmsg_type == SCM_RIGHTS:
filehandles.fromstring(bytes(
cdata[:len(cdata) - len(cdata) % filehandles.itemsize]))
try:
filehandles.fromstring(bytes(
cdata[:len(cdata) - len(cdata) % filehandles.itemsize]))
except AttributeError:
filehandles.frombytes(bytes(
cdata[:len(cdata) - len(cdata) % filehandles.itemsize]))
data = json.loads(bytes(data))
return ClientFile(data['filename'], data['mode'], filehandles[0])
else:
+16 -18
View File
@@ -1,19 +1,23 @@
%define name confluent_client
%define version #VERSION#
%define fversion %{lua:
sv, _ = string.gsub("#VERSION#", "[~]", "-")
print(sv)
}
%define release 1
Summary: Client libraries and utilities for confluent
Name: %{name}
Version: %{version}
Release: %{release}
Source0: %{name}-%{version}.tar.gz
Source0: %{name}-%{fversion}.tar.gz
License: Apache2
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: %{_prefix}
BuildArch: noarch
Vendor: Jarrod Johnson <jjohnson2@lenovo.com>
Url: http://xcat.sf.net/
Vendor: Lenovo
Url: http://github.com/lenovo/confluent
Obsoletes: confluent_common
%description
@@ -21,28 +25,20 @@ This package enables python development and command line access to
a confluent server.
%prep
%setup -n %{name}-%{version} -n %{name}-%{version}
%setup -n %{name}-%{fversion}
%build
%if "%{dist}" == ".el8"
python3 setup.py build
%else
%if "%{dist}" == ".el9"
python3 setup.py build
%else
%if "%{dist}" == ".el7"
python2 setup.py build
%endif
%else
python3 setup.py build
%endif
%install
%if "%{dist}" == ".el8"
python3 setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES --install-scripts=/opt/confluent/bin --install-purelib=/opt/confluent/lib/python
%else
%if "%{dist}" == ".el9"
python3 setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES --install-scripts=/opt/confluent/bin --install-purelib=/opt/confluent/lib/python
%else
%if "%{dist}" == ".el7"
python2 setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES --install-scripts=/opt/confluent/bin --install-purelib=/opt/confluent/lib/python
%endif
%else
python3 setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES --install-scripts=/opt/confluent/bin --install-purelib=/opt/confluent/lib/python
%endif
@@ -51,4 +47,6 @@ rm -rf $RPM_BUILD_ROOT
%files -f INSTALLED_FILES
%license /opt/confluent/share/licenses/confluent_client/LICENSE
%license /opt/confluent/share/licenses/confluent_client/COPYRIGHT
%defattr(-,root,root)
/opt/confluent
+41 -5
View File
@@ -82,6 +82,17 @@ function _confluent_generic_completion()
return;
fi
}
function _confluent_generic_ng_completion()
{
_confluent_get_args
if [ $NUMARGS -ge 3 ] && [ ! -z "$GENNED" ]; then
COMPREPLY=($(compgen -W "$GENNED" -- ${COMP_WORDS[COMP_CWORD]}))
fi
if [ $NUMARGS -lt 3 ]; then
_confluent_ng_completion
return;
fi
}
_confluent_nodeidentify_completion()
{
COMP_CANDIDATES=("on,off,blink -h")
@@ -142,15 +153,15 @@ _confluent_osimage_completion()
{
_confluent_get_args
if [ $NUMARGS == 2 ]; then
COMPREPLY=($(compgen -W "initialize import updateboot" -- ${COMP_WORDS[COMP_CWORD]}))
COMPREPLY=($(compgen -W "initialize import importcheck updateboot rebase" -- ${COMP_WORDS[COMP_CWORD]}))
return
elif [ ${CMPARGS[1]} == 'initialize' ]; then
COMPREPLY=($(compgen -W "-h -u -s -t -i" -- ${COMP_WORDS[COMP_CWORD]}))
elif [ ${CMPARGS[1]} == 'import' ]; then
elif [ ${CMPARGS[1]} == 'import' ] || [ ${CMPARGS[1]} == 'importcheck' ]; then
compopt -o default
COMPREPLY=()
return
elif [ ${CMPARGS[1]} == 'updateboot' ]; then
elif [ ${CMPARGS[1]} == 'updateboot' -o ${CMPARGS[1]} == 'rebase' ]; then
COMPREPLY=($(compgen -W "-n $(confetty show /deployment/profiles|sed -e 's/\///')" -- "${COMP_WORDS[COMP_CWORD]}"))
return
fi
@@ -268,7 +279,20 @@ _confluent_nodeattrib_completion()
_confluent_generic_completion
}
_confluent_define_completion()
{
COMP_CANDIDATES=$(nodegroupattrib 'everything' all | awk '{print $2}'|sed -e 's/://')
_confluent_get_args
if [ $NUMARGS -ge 3 ] && [ ! -z "$GENNED" ]; then
COMPREPLY=($(compgen -W "$GENNED" -- ${COMP_WORDS[COMP_CWORD]}))
fi
}
_confluent_nodegroupattrib_completion()
{
COMP_CANDIDATES=$(nodegroupattrib 'everything' all | awk '{print $2}'|sed -e 's/://')
_confluent_generic_ng_completion
}
_confluent_nn_completion()
{
_confluent_get_args
@@ -323,18 +347,30 @@ _confluent_ng_completion()
COMPREPLY=($(compgen -W "$(confetty show /nodegroups|sed -e 's/\///' -e s/^/$PREFIX/)" -- "${COMP_WORDS[COMP_CWORD]}"))
}
_confluent_nodediscover_completion()
{
_confluent_get_args
if [ $NUMARGS == 2 ]; then
COMPREPLY=($(compgen -W "list assign rescan clear subscribe unsubscribe register" -- ${COMP_WORDS[COMP_CWORD]}))
return;
fi
}
complete -F _confluent_nodediscover_completion nodediscover
complete -F _confluent_nodeattrib_completion nodeattrib
complete -F _confluent_nodeattrib_completion nodegroupattrib
complete -F _confluent_nr_completion nodebmcreset
complete -F _confluent_nodesetboot_completion nodeboot
complete -F _confluent_nr_completion nodeconfig
complete -F _confluent_nn_completion nodeconsole
complete -F _confluent_define_completion nodedefine
complete -F _confluent_define_completion nodegroupdefine
complete -F _confluent_nr_completion nodeeventlog
complete -F _confluent_nodefirmware_completion nodefirmware
complete -F _confluent_nodedeploy_completion nodedeploy
complete -F _confluent_osimage_completion osdeploy
complete -F _confluent_imgutil_completion imgutil
complete -F _confluent_ng_completion nodegroupattrib
complete -F _confluent_nodegroupattrib_completion nodegroupattrib
complete -F _confluent_ng_completion nodegroupremove
complete -F _confluent_nr_completion nodehealth
complete -F _confluent_nodeidentify_completion nodeidentify
@@ -0,0 +1,28 @@
confluent2hosts(8) -- Generate /etc/hosts entries for nodes
========================================================
## SYNOPSIS
`confluent2hosts -i <ip expression> -n <name expression> <noderange>`
`confluent2hosts -a <noderange>`
## DESCRIPTION
`confluent2hosts` can be used to help generate /etc/hosts entries for a
noderange. There are two general approaches.
It can be used ad-hoc, using -i and -n to specify the address and name portions respectively. This accepts the standard confluent expression syntax, allowing for things like 172.30.1.{n1} or {node}.{dns.domain} or {bmc}.
It can also read from the confluent db, using `-a`. In this mode, each net.<value>.<attribute> group is pulled together into hosts lines. ipv4_address and ipv6_address fields are associated with the corresponding hostname attributes. You can use `-f` to put the FQDN first.
## EXAMPLES
* Generate /etc/hosts entries ad-hoc using default name:
`# confluent2hosts -i 10.2.3.{n1} d9-d12`
* Generate /etc/hosts entries ad-hoc using alternative name:
`# confluent2hosts -i 10.2.3.{n1} -n "{node}-alt {node}-alt.{dns.domain}" d9-d12`
* Generate /etc/hosts entries using the confluent DB as a reference:
`# confluent2hosts -a d9-d12`
@@ -38,5 +38,8 @@ the json files (password protected, removed from the files, or unprotected).
keys do not change and as such they do not require
incremental backup.
* `-y`, `--yaml
Use YAML instead of JSON as file format
* `-h`, `--help`:
Show help message and exit
+139
View File
@@ -0,0 +1,139 @@
# imgutil(1) -- Work with confluent OS cloning and diskless images
## SYNOPSIS
`imgutil` `build` [<options>] <scratchdir>
`imgutil` `exec` [<options>] <scratchdir> [<cmd>...]
`imgutil` `unpack` <profilename> <scratchdir>
`imgutil` `pack` [<options>] <scratchdir> <profilename>
`imgutil` `capture` <node> <profilename>
## DESCRIPTION
**imgutil** is a utility for creating, managing, and deploying OS images for diskless boot and system cloning in a Confluent environment. It supports building images from scratch, capturing images from running systems, and packing/unpacking diskless profiles.
## COMMANDS
* `build`:
Build a new diskless image from scratch in the specified scratch directory.
* `exec`:
Start the specified scratch directory as a container and optionally run a command inside it.
* `unpack`:
Unpack a diskless image profile to a scratch directory for modification.
* `pack`:
Pack a scratch directory into a diskless profile that can be deployed.
* `capture`:
Capture an image for cloning from a running system.
## BUILD OPTIONS
* `-r`, `--addrepos` <repository>:
Repositories to add in addition to the main source. May be specified multiple times.
* `-p`, `--packagelist` <file>:
Filename of package list to replace default pkglist.
* `-a`, `--addpackagelist` <file>:
A list of additional packages to include. May be specified multiple times.
* `-s`, `--source` <directory>:
Directory to pull installation from, typically a subdirectory of `/var/lib/confluent/distributions`. By default, the repositories for the build system are used. For Ubuntu, this is not supported; the build system repositories are always used.
* `-y`, `--non-interactive`:
Avoid prompting for confirmation.
* `-v`, `--volume` <mount>:
Directory to make available in the build environment. `-v /` will cause it to be mounted in image as `/run/external/`. `-v /:/run/root` will override the target to be `/run/root`. Something like `/var/lib/repository:-` will cause it to mount to the identical path inside the image. May be specified multiple times.
* <scratchdir>:
Directory to build new diskless root in.
## EXEC OPTIONS
* `-v`, `--volume` <mount>:
Directory to make available in the build environment. `-v /` will cause it to be mounted in image as `/run/external/`. `-v /:/run/root` will override the target to be `/run/root`. May be specified multiple times.
* <scratchdir>:
Directory of an unpacked diskless root.
* <cmd>:
Optional command to run (defaults to a shell).
## UNPACK OPTIONS
* <profilename>:
The diskless OS profile to unpack.
* <scratchdir>:
Directory to extract diskless root to.
## PACK OPTIONS
* `-b`, `--baseprofile` <profile>:
Profile to copy extra info from. For example, to make a new version of an existing profile, reference the previous one as baseprofile.
* `-u`, `--unencrypted`:
Pack an unencrypted image rather than encrypting.
* <scratchdir>:
Directory containing diskless root.
* <profilename>:
The desired diskless OS profile name to pack the root into.
## CAPTURE OPTIONS
* <node>:
Node to capture image from.
* <profilename>:
Profile name for captured image.
## EXAMPLES
Build a diskless image from a distribution:
imgutil build -s alma-9.6-x86_64 /tmp/myimage
Execute a shell in an unpacked image:
imgutil exec /tmp/myimage
Execute a specific command in an image:
imgutil exec /tmp/myimage /bin/rpm -qa
Unpack an existing profile for modification:
imgutil unpack myprofile /tmp/myimage
Pack a modified image into a new profile:
imgutil pack /tmp/myimage myprofile-v2
Capture an image from a running node:
imgutil capture node01 production-image
## FILES
* `/var/lib/confluent/public/os/`:
Default location for OS profiles.
* `/var/lib/confluent/private/os/`:
Location for encrypted image keys and private data.
* `/var/lib/confluent/distributions/`:
Default location for installation sources.
## SEE ALSO
osdeploy(8)
## AUTHOR
Written for the Confluent project.
+30
View File
@@ -0,0 +1,30 @@
nodeapply(8) -- Execute command on many nodes in a noderange through ssh
=========================================================================
## SYNOPSIS
`nodeapply [options] <noderange>`
## DESCRIPTION
Provides shortcut access to a number of common operations against deployed
nodes. These operations include refreshing ssh certificates and configuration,
rerunning syncflies, and executing specified postscripts.
## OPTIONS
* `-k`, `--security`
Refresh SSH configuration (hosts.equiv and node SSH certificates)
* `-F`, `--sync`
Rerun syncfiles from deployed profile
* `-P SCRIPTS`, `--scripts=SCRIPTS`
Re-run specified scripts, with full path under scripts specified, e.g. post.d/scriptname,firstboot.d/otherscriptname
* `-c COUNT`, `-f COUNT`, `--count=COUNT`
Specify the maximum number of instances to run concurrently
* `-m MAXNODES`, `--maxnodes=MAXNODES`
Specify a maximum number of nodes to run remote ssh command to, prompting
if over the threshold
+35 -7
View File
@@ -7,7 +7,8 @@ nodeattrib(8) -- List or change confluent nodes attributes
`nodeattrib <noderange> [<nodeattribute1=value1> <nodeattribute2=value2> ...]`
`nodeattrib -c <noderange> <nodeattribute1> <nodeattribute2> ...`
`nodeattrib -e <noderange> <nodeattribute1> <nodeattribute2> ...`
`nodeattrib -p <noderange> <nodeattribute1> <nodeattribute2> ...`
`nodeattrib -p <noderange> <nodeattribute1> <nodeattribute2> ...`
`nodeattrib <noderange> -s <attributes.batch> ...`
## DESCRIPTION
@@ -23,6 +24,8 @@ For a full list of attributes, run `nodeattrib <node> all` against a node.
If `-c` is specified, this will set the nodeattribute to a null value.
This is different from setting the value to an empty string.
Arbitrary custom attributes can also be created with the `custom.` prefix.
Attributes may be specified by wildcard, for example `net.*switch` will report
all attributes that begin with `net.` and end with `switch`.
@@ -53,12 +56,18 @@ to a blank value will allow masking a group defined attribute with an empty valu
* `-e`, `--environment`:
Set specified attributes based on exported environment variable of matching name.
Environment variable names may be lower case or all upper case.
Replace . with _ as needed (e.g. info.note may be specified as either $info_note or $INFO_NOTE
Replace . with _ as needed (e.g. info.note may be specified as either $info_note or $INFO_NOTE)
* `-p`, `--prompt`:
Request interactive prompting to provide values rather than the command line
or environment variables.
* `-s`, `--set`:
Set attributes using a batch file rather than the command line. The attributes in the batch file
can be specified as one line of key=value pairs simmilar to command line or each attribute can
be in its own line. Lines that start with # sign will be read as a comment. See EXAMPLES for batch
file syntax.
* `-m MAXNODES`, `--maxnodes=MAXNODES`:
Prompt if trying to set attributes on more than
specified number of nodes.
@@ -83,12 +92,12 @@ to a blank value will allow masking a group defined attribute with an empty valu
`# nodeattrib n1,n2 hardwaremanagement --blame`
`n1: hardwaremanagement.manager: 172.30.3.1`
`n1: hardwaremanagement.method: ipmi (inherited from group everything)`
`n1: hardwaremanagement.switch: r8e1`
`n1: hardwaremanagement.switchport: 14`
`n1: net.switch: r8e1`
`n1: net.switchport: 14`
`n2: hardwaremanagement.manager: 172.30.3.2`
`n2: hardwaremanagement.method: ipmi (inherited from group everything)`
`n2: hardwaremanagement.switch: r8e1`
`n2: hardwaremanagement.switchport: 2`
`n2: net.switch: r8e1`
`n2: net.switchport: 2`
* Listing matching nodes of a simple noderange that are set:
`# nodeattrib n1-n2 current`
@@ -116,6 +125,25 @@ to a blank value will allow masking a group defined attribute with an empty valu
`d1: net.pxe.switch: pxeswitch1`
`d1: net.switch:`
* Setting attributes using a batch file with syntax similar to command line:
`# cat nodeattributes.batch`
`# power`
`power.psu1.outlet=3 power.psu1.pdu=pdu2`
`# nodeattrib n41 -s nodeattributes.batch`
`n41: 3`
`n41: pdu2`
* Setting attributes using a batch file with syntax where each attribute is in its own line:
`# cat nodeattributes.batch`
`# management`
`custom.mgt.switch=switch_main`
`custom.mgt.switch.port=swp4`
`# nodeattrib n41 -s nodeattributes.batch`
`n41: switch_main`
`n41: swp4`
## SEE ALSO
nodegroupattrib(8), nodeattribexpressions(5)
@@ -0,0 +1,28 @@
nodebmcpassword(8) -- Change management controller password for a specified user
=========================================================
## SYNOPSIS
`nodebmcpassword <noderange> <username> <new_password>`
## DESCRIPTION
`nodebmcpassword` allows you to change the management controller password for a user on a specified noderange
## OPTIONS
* `-m MAXNODES`, `--maxnodes=MAXNODES`:
Number of nodes to affect before prompting for
confirmation
* `-h`, `--help`:
Show help message and exit
## EXAMPLES:
* Reset the management controller for nodes n1 through n4:
`# nodebmcreset n1-n4`
`n1: Password Change Successful`
`n2: Password Change Successful`
`n3: Password Change Successful`
`n4: Password Change Successful`
+1 -2
View File
@@ -49,8 +49,7 @@ actually be in effect until a reboot.
* `-r COMPONENT`, `--restoredefault=COMPONENT`:
Request that the specified component of the targeted nodes will have its
configuration reset to default. Currently the only component implemented
is uefi.
configuration reset to default. The component may be "uefi" or "bmc".
* `-m MAXNODES`, `--maxnodes=MAXNODES`:
Specify a maximum number of nodes to configure, prompting if over
+61 -3
View File
@@ -2,7 +2,7 @@ nodeconsole(8) -- Open a console to a confluent node
=====================================================
## SYNOPSIS
`nodeconsole [options] <noderange>`
`nodeconsole [options] <noderange> [kill][-- [passthroughoptions]]`
## DESCRIPTION
@@ -16,11 +16,58 @@ will initiate an automatic retry interval that is randomized between 2 and 4 min
The reopen escape sequence below requests an immediate retry, as does connecting
a new session.
When a windowed console is open the `nodeconsole <noderange> kill` command will kill the
console process which will result in the console window closing.
## OPTIONS
* `-i N`, `--interval`:
For screenshot mode, fetch new screenshots and overwrite old screenshots every N seconds.
For example, `nodeconsole r3u[21:24] -tsi 3` will tile screenshots of r3u21 through r3u24 and
refresh them every 3 seconds.
* `-t`, `--tile`:
Use tmux to arrange consoles of the given noderange into a tiled layout on
the terminal screen
For text consoles, use tmux to arrange consoles of the given noderange into a tiled layout on
the terminal screen. If using 'screenshot' mode, divide the terminal and display the images
in a grid.
* `-l`, `--log`:
Perform a log reply on the current, local log in /var/log/confluent/consoles.
If in collective mode, this only makes sense to use on the current collective
manager at this time.
* `-T`, `--Timestamp`:
Dump the log with Timpstamps on the current, local log in /var/log/confluent/consoles.
If in collective mode, this only makes sense to use on the current collective
manager at this time.
* `-s`, `--screenshot`:
Attempt to grab screenshot(s) and render using a terminal
image protocol. The image protocol defaults to kitty, and
can be selected by CONFLUENT_IMAGE_PROTOCOL environment variable.
Supported protocols are kitty, iterm, and, sixel (sixel only
if PySixel is installed). This only presents screenshots, there
is no input supported to graphical consoles from a terminal.
* `-w`, `--windowed`:
Open terminal windows for each node. The
environment variable **NODECONSOLE_WINDOWED_COMMAND**
should be set, which should be a text string corresponding
to a command that can be used to open a windowed console,
omitting the `nodeconsole <noderange>` part of the
command, for example, to open a set of consoles for a
range of nodes in separate xterm windows, set
**NODECONSOLE_WINDOWED_COMMAND** to `xterm -e`. To open a
set of consoles for a range of nodes in separate
GNOME Terminal windows with a size of 100 columns and
31 rows, set **NODECONSOLE_WINDOWED_COMMAND**
to `gnome-terminal --geometry 100x31 --` or in a WSL
environment, to open a set of consoles for a range of
nodes in separate Windows Terminal windows, with the
title set for each node, set **NODECONSOLE_WINDOWED_COMMAND**
to `wt.exe wsl.exe -d AlmaLinux-8 --shell-type login. If the
NODECONSOLE_WINDOWED_COMMAND environment variable isn't set,
xterm will be used bydefault.
## ESCAPE SEQUENCE COMMANDS
@@ -61,3 +108,14 @@ keystroke will be interpreted as a command. The following commands are availabl
Get a list of supported commands
* `<ent>`:
Hit enter to skip entering a command at the escape prompt.
## PASSTHROUGH OPTIONS
While opening a windowed console with xterm or any other console of choice. The
nodeconsole command gives capality to specify passthrough options targeted at
the console. All options after the -- will be parsed the console program. For
example, opening a windowed console using xterm with a black background.
`nodeconconsole -w n1 -- -bg black`
+12 -3
View File
@@ -5,9 +5,12 @@ nodediscover(8) -- List or manage confluent node discovery
`nodediscover rescan`
`nodediscover [options] list`
`nodediscover [options] assign`
`nodediscover [options] rescan`
`nodediscover [options] clear`
`nodediscover [options] assign`
`nodediscover [options] rescan`
`nodediscover [options] clear`
`nodediscover [options] subscribe [switch]`
`nodediscover [options] unsubscribe [switch]`
`nodediscover [options] register [Addresses, e.g. 192.168.1.2 or 192.168.1.0/24 or 192.168.1.1-192.168.1.28]`
## DESCRIPTION
@@ -35,6 +38,12 @@ scan is the best approach to catch something that appears to be missing.
**nodedsicover clear** requests the server forget about a selection of
detected device. It takes the same arguments as **nodediscover list**.
**nodediscover subscribe** and **unsubscribe** instructs confluent to subscribe to or
unsubscribe from the designated switch running affluent with system discovery support.
**nodediscover register** instructs confluent to perform a remote probe of an address, subnet,
or range of IP addresses.
## CSV FORMAT
The CSV format used by nodediscover consists of one header describing the
@@ -15,6 +15,15 @@ noderange.
* `-m MAXNODES`, `--maxnodes=MAXNODES`:
Specify a maximum number of nodes to clear if clearing log, prompting if
over the threshold
* `-l LINES`, `--lines=LINES`:
return the last <n> entries for each node in the eventlog.
* `-t TIMEFRAME`, `--timeframe=TIMEFRAME`:
return entries within a specified timeframe for each node's event log.
This will return entries from the last <n> hours or days. 1h would be
entries from with the last one hour.
* `-h`, `--help`:
Show help message and exit
+8 -2
View File
@@ -3,7 +3,7 @@ nodefirmware(8) -- Report firmware information on confluent nodes
## SYNOPSIS
`nodefirmware <noderange> [list][update [--backup <file>]]|[<components>]`
`nodefirmware <noderange> [list][updatestatus][update [--backup <file>]]|[<components>]`
## DESCRIPTION
@@ -17,6 +17,9 @@ not be relevant to redfish. Additionally, the Lenovo XCC makes certain
information available over IPMI that is not otherwise available (for example
the FPGA version where applicable).
The updatestatus argument will describe the state of firmware updates on the
nodes.
In the update form, it accepts a single file and attempts to update it using
the out of band facilities. Firmware updates can end in one of three states:
@@ -32,7 +35,10 @@ the out of band facilities. Firmware updates can end in one of three states:
* `-m MAXNODES`, `--maxnodes=MAXNODES`:
When updating, prompt if more than the specified number of servers will
be affected
* `-p PARAMETERFILE`, `--paramaterfile=PARAMETERFILE`:
For updating, a parameter file to provife along with the update payload
* `-h`, `--help`:
Show help message and exit
@@ -11,7 +11,7 @@ nodegroupattrib(8) -- List or change confluent nodegroup attributes
## DESCRIPTION
`nodegroupattrip` queries the confluent server to get information about nodes.
`nodegroupattrib` queries the confluent server to get information about nodes.
In the simplest form, it simply takes the given group and lists the attributes of that group.
Contrasted with nodeattrib(8), settings managed by nodegroupattrib will be added
@@ -0,0 +1,42 @@
nodel2traceroute(8) -- returns the layer 2 route through an Ethernet network managed by confluent given 2 end points.
==============================
## SYNOPSIS
`nodel2traceroute [options] <start_node> <end_noderange>`
## DESCRIPTION
**nodel2traceroute** is a command that returns the layer 2 route for the configered interfaces in nodeattrib.
It can also be used with the -i and -e options to check against specific interfaces on the endpoints. If the
--interface or --eface option are not used then the command will check for routes against all the defined
interfaces in nodeattrib (net.*.switch) for the nodes.
## PREREQUISITES
**nodel2traceroute** the net.<interface>.switch attributes have to be set on the end points if endpoint is not a switch
## OPTIONS
* ` -e` EFACE, --eface=INTERFACE
interface to check against for the second end point or end points if using checking against multiple nodes
* ` -i` INTERFACE, --interface=INTERFACE
interface to check against for the first end point
* ` -c` CUMULUS, --cumulus=CUMULUS
return layer 2 route through cumulus switches only
* `-h`, `--help`:
Show help message and exit
## EXAMPLES
* Checking route between two nodes:
`# nodel2traceroute n244 n1851`
`n244 to n1851: ['switch114']`
* Checking route from one node to multiple nodes:
`# nodel2traceroute n244 n1833,n1851`
`n244 to n1833: ['switch114', 'switch7', 'switch32', 'switch253', 'switch85', 'switch72', 'switch21', 'switch2', 'switch96', 'switch103', 'switch115']
n244 to n1851: ['switch114']`
+3 -2
View File
@@ -4,7 +4,7 @@ nodelist(8) -- List confluent nodes and their attributes
## SYNOPSIS
`nodelist <noderange>`
`nodelist <noderange> [-b] <nodeattribute>...`
`nodelist <noderange> [-b] [-d] {string} <nodeattribute>...`
## DESCRIPTION
@@ -24,7 +24,8 @@ all attributes that begin with `net.` and end with `switch`.
* `-b`, `--blame`:
Annotate inherited and expression based attributes to show their base value.
* `-d`, `--delim`:
Choose a delimiter to separat the values. Default - ENTER.
## EXAMPLES
* Listing matching nodes of a simple noderange:
`# nodelist n1-n4`
+7
View File
@@ -32,6 +32,13 @@ BMCs map a virtual USB device to that url. Content is loaded on demand, and
as such that URL is referenced potentially once for every IO operation that
the host platform attempts.
## NOTES
When doing an attach of an https:// url, you may hit an error if you have not enrolled your certificate authority.
In a general confluent environment, you can usually address it by:
`# for cert in /var/lib/confluent/public/site/tls/*.pem; do nodecertutil s1-s4 installbmccacert $cert; done`
## OPTIONS
* `-h`, `--help`:
+10 -1
View File
@@ -14,7 +14,9 @@ It can also be used with the `-s` flag to change the ping location to something
* `-h`, `--help`:
Show help message and exit
* `-s` SUBSTITUTENAME, --substitutename=SUBSTITUTENAME
Use a different name other than the nodename for ping
Use a different name other than the nodename for ping. This may be a
expression, such as {bmc} or, if no { character is present, it is treated as a suffix. -s -eth1 would make n1 become n1-eth1, for example.
## EXAMPLES
* Pinging a node :
@@ -31,6 +33,13 @@ It can also be used with the `-s` flag to change the ping location to something
`# nodeping -s {bmc} <noderange>`
` Node-bmc : ping`
* Pinging by specifying a suffix:
`# nodeping d1-d4 -s -eth1`
`d2-eth1: no_ping`
`d1-eth1: no_ping`
`d3-eth1: no_ping`
`d4-eth1: no_ping`
* Fail to ping node:
`# nodeping <node>`
`node : no_ping`
+3
View File
@@ -16,6 +16,9 @@ noderange. This will present progress as percentage for all nodes.
Specify how many rsync executions to do concurrently. If noderange
exceeds the count, then excess nodes will wait until one of the
active count completes.
* `-s`, `--substitutename`:
'Use a different name other than the nodename for rsync'
* `-m MAXNODES`, `--maxnodes=MAXNODES`:
Specify a maximum number of nodes to run rsync to, prompting if over the
+3 -1
View File
@@ -19,7 +19,9 @@ interval of 1 second is used.
## OPTIONS
* `-c`, `--csv`:
Organize output into CSV format, one sensor per column.
Organize output into CSV format, one sensor per column. Note that while normally nodesensors reports
sensors in order as returned by server, CSV output enforces consistency by sorting after receiving
the results, which may have a different ordering than non-CSV usage of nodesensors.
* `-i`, `--interval`=**SECONDS**:
Repeat data gathering waiting, waiting the specified time between samples. Unless `-n` is
+4 -2
View File
@@ -5,6 +5,7 @@ osdeploy(8) --- Configure general OS deployment facilities of confluent
`osdeploy import <iso>`
`osdeploy updateboot <profile>`
`osdeploy rebase <profile>`
`osdeploy initialize [-h] [-g] [-u] [-s] [-k] [-t] [-p] [-i] [-l] [-a]`
## DESCRIPTION
@@ -13,5 +14,6 @@ osdeploy(8) --- Configure general OS deployment facilities of confluent
`import` subcommand will generate profiles from an iso image. `updateboot` will take any
changes in the specified update that need to be pushed into boot configuration and/or images
and ensure those needed changes are performed. `initialize` provides assistance in setting
up the most commonly required facilities. Run `osdeploy initialize -h` for more detail
on the options offered by `osdeploy initialize`
up the most commonly required facilities. `rebase` has confluent attempt to update profile
content that came from /opt/confluent in an rpm update, if profile supports it.
Run `osdeploy initialize -h` for more detail on the options offered by `osdeploy initialize`.
+7 -3
View File
@@ -2,7 +2,7 @@ from setuptools import setup
import os
data_files = [('/etc/profile.d', ['confluent_env.sh', 'confluent_env.csh']),
('/opt/confluent/share/licenses/confluent_client/', ['LICENSE'])
('/opt/confluent/share/licenses/confluent_client/', ['LICENSE', 'COPYRIGHT'])
]
try:
scriptlist = ['bin/{0}'.format(d) for d in os.listdir('bin/')]
@@ -15,10 +15,14 @@ except OSError:
setup(
name='confluent_client',
version='#VERSION#',
author='Jarrod Johnson',
author='Lenovo',
author_email='jjohnson2@lenovo.com',
url='http://xcat.sf.net/',
url='http://github.com/lenovo/confluent/',
license='Apache-2.0',
description='Command line client and libraries for confluent management server',
long_description='Command line client and libraries for confluent management server',
packages=['confluent'],
platforms=['Linux'],
scripts=scriptlist,
data_files=data_files,
)
@@ -0,0 +1,74 @@
#!/usr/bin/python3
import glob
import gzip
import base64
import os
import subprocess
import sys
import tempfile
def collect_certificates(tmpdir):
certdata = ''
for cacert in glob.glob(f'{tmpdir}/*.pem'):
with open(cacert, 'r') as f:
certdata += f.read()
return certdata
def embed_certificates(incfg, certdata):
if not certdata:
raise Exception('No certificates found to embed')
incfg = incfg.replace('%CONFLUENTCERTCOLL%', certdata)
return incfg
def embed_identity(incfg, identityjson):
incfg = incfg.replace('%IDENTJSON%', identityjson)
return incfg
def embed_apiclient(incfg, apiclient):
with open(apiclient, 'r') as f:
apiclientdata = f.read()
compressed = gzip.compress(apiclientdata.encode())
encoded = base64.b64encode(compressed).decode()
incfg = incfg.replace('%APICLIENTZ64%', encoded)
return incfg
def embed_data(tmpdir, outfile):
templatefile = f'{tmpdir}/bfb.cfg.template'
with open(templatefile, 'r') as f:
incfg = f.read()
certdata = collect_certificates(tmpdir)
incfg = embed_certificates(incfg, certdata)
with open(f'{tmpdir}/identity.json', 'r') as f:
identityjson = f.read()
incfg = embed_identity(incfg, identityjson)
incfg = embed_apiclient(incfg, f'{tmpdir}/../apiclient')
with open(outfile, 'w') as f:
f.write(incfg)
def get_identity_json(node):
identity_file = f'/var/lib/confluent/private/site/identity_files/{node}.json'
try:
with open(identity_file, 'r') as f:
return f.read()
except FileNotFoundError:
return None
if __name__ == '__main__':
if len(sys.argv) != 4:
print("Usage: bfb-autoinstall <node> <bfbfile> <rshim>")
sys.exit(1)
node = sys.argv[1]
bfbfile = sys.argv[2]
rshim = sys.argv[3]
os.chdir(os.path.dirname(os.path.abspath(__file__)))
currdir = os.getcwd()
tempdir = tempfile.mkdtemp(prefix=f'bfb-autoinstall-{node}-')
embed_data(f'{currdir}/{node}', f'{tempdir}/bfb.cfg')
subprocess.check_call(['bfb-install', '-b', bfbfile, '-c', f'{tempdir}/bfb.cfg', '-r', rshim])
@@ -0,0 +1,74 @@
#!/usr/bin/python3
import glob
import gzip
import base64
import os
import subprocess
import sys
import tempfile
def collect_certificates(tmpdir):
certdata = ''
for cacert in glob.glob(f'{tmpdir}/*.pem'):
with open(cacert, 'r') as f:
certdata += f.read()
return certdata
def embed_certificates(incfg, certdata):
if not certdata:
raise Exception('No certificates found to embed')
incfg = incfg.replace('%CONFLUENTCERTCOLL%', certdata)
return incfg
def embed_identity(incfg, identityjson):
incfg = incfg.replace('%IDENTJSON%', identityjson)
return incfg
def embed_apiclient(incfg, apiclient):
with open(apiclient, 'r') as f:
apiclientdata = f.read()
compressed = gzip.compress(apiclientdata.encode())
encoded = base64.b64encode(compressed).decode()
incfg = incfg.replace('%APICLIENTZ64%', encoded)
return incfg
def embed_data(tmpdir, outfile):
templatefile = f'{tmpdir}/bfb.cfg.template'
with open(templatefile, 'r') as f:
incfg = f.read()
certdata = collect_certificates(tmpdir)
incfg = embed_certificates(incfg, certdata)
with open(f'{tmpdir}/identity.json', 'r') as f:
identityjson = f.read()
incfg = embed_identity(incfg, identityjson)
incfg = embed_apiclient(incfg, f'{tmpdir}/../apiclient')
with open(outfile, 'w') as f:
f.write(incfg)
def get_identity_json(node):
identity_file = f'/var/lib/confluent/private/site/identity_files/{node}.json'
try:
with open(identity_file, 'r') as f:
return f.read()
except FileNotFoundError:
return None
if __name__ == '__main__':
if len(sys.argv) != 4:
print("Usage: bfb-autoinstall <node> <bfbfile> <rshim>")
sys.exit(1)
node = sys.argv[1]
bfbfile = sys.argv[2]
rshim = sys.argv[3]
os.chdir(os.path.dirname(os.path.abspath(__file__)))
currdir = os.getcwd()
tempdir = tempfile.mkdtemp(prefix=f'bfb-autoinstall-{node}-')
embed_data(f'{currdir}/{node}', f'{tempdir}/bfb.cfg')
subprocess.check_call(['bfb-install', '-b', bfbfile, '-c', f'{tempdir}/bfb.cfg', '-r', rshim])
@@ -0,0 +1,76 @@
function bfb_modify_os() {
echo 'ubuntu:!' | chpasswd -e
mkdir -p /mnt/opt/confluent/bin/
cat > /mnt/opt/confluent/bin/confluentbootstrap.sh << 'END_OF_EMBED'
#!/bin/bash
cat > /usr/local/share/ca-certificates/confluent.crt << 'END_OF_CERTS'
%CONFLUENTCERTCOLL%
END_OF_CERTS
update-ca-certificates
mkdir -p /opt/confluent/bin /etc/confluent/
cp /usr/local/share/ca-certificates/confluent.crt /etc/confluent/ca.pem
cat > /opt/confluent/bin/apiclient.gz.b64 << 'END_OF_CLIENT'
%APICLIENTZ64%
END_OF_CLIENT
base64 -d /opt/confluent/bin/apiclient.gz.b64 | gunzip > /opt/confluent/bin/apiclient
cat > /etc/confluent/ident.json << 'END_OF_IDENT'
%IDENTJSON%
END_OF_IDENT
python3 /opt/confluent/bin/apiclient -i /etc/confluent/ident.json /confluent-api/self/deploycfg2 > /etc/confluent/confluent.deploycfg
PROFILE=$(grep ^profile: /etc/confluent/confluent.deploycfg |awk '{print $2}')
ROOTPASS=$(grep ^rootpassword: /etc/confluent/confluent.deploycfg | awk '{print $2}'|grep -v null)
if [ -n "$ROOTPASS" ]; then
echo root:$ROOTPASS | chpasswd -e
echo "ubuntu:$ROOTPASS" | chpasswd -e
else
echo 'ubuntu:!' | chpasswd -e
fi
cntmp=$(mktemp -d)
cd "$cntmp" || { echo "Failed to cd to temporary directory $cntmp"; exit 1; }
touch /etc/confluent/confluent.deploycfg
python3 /opt/confluent/bin/apiclient /confluent-public/os/$PROFILE/scripts/confignet > confignet
python3 confignet
cd -
rm -rf "$cntmp"
python3 /opt/confluent/bin/apiclient /confluent-public/os/$PROFILE/scripts/functions > /etc/confluent/functions
bash /etc/confluent/functions run_remote setupssh
for cert in /etc/ssh/ssh*-cert.pub; do
if [ -s $cert ]; then
echo HostCertificate $cert >> /etc/ssh/sshd_config.d/90-confluent.conf
fi
done
mkdir -p /var/log/confluent
chmod 700 /var/log/confluent
touch /var/log/confluent/confluent-firstboot.log
touch /var/log/confluent/confluent-post.log
chmod 600 /var/log/confluent/confluent-post.log
chmod 600 /var/log/confluent/confluent-firstboot.log
exec >> /var/log/confluent/confluent-post.log
exec 2>> /var/log/confluent/confluent-post.log
bash /etc/confluent/functions run_remote_python syncfileclient
bash /etc/confluent/functions run_remote_parts post.d
bash /etc/confluent/functions run_remote_config post.d
exec >> /var/log/confluent/confluent-firstboot.log
exec 2>> /var/log/confluent/confluent-firstboot.log
bash /etc/confluent/functions run_remote_parts firstboot.d
bash /etc/confluent/functions run_remote_config firstboot.d
python3 /opt/confluent/bin/apiclient /confluent-api/self/updatestatus -d 'status: staged'
python3 /opt/confluent/bin/apiclient /confluent-api/self/updatestatus -d 'status: complete'
systemctl disable confluentbootstrap
rm /etc/systemd/system/confluentbootstrap.service
END_OF_EMBED
chmod +x /mnt/opt/confluent/bin/confluentbootstrap.sh
cat > /mnt/etc/systemd/system/confluentbootstrap.service << EOS
[Unit]
Description=First Boot Process
Requires=network-online.target
After=network-online.target
[Service]
ExecStart=/opt/confluent/bin/confluentbootstrap.sh
[Install]
WantedBy=multi-user.target
EOS
chroot /mnt systemctl enable confluentbootstrap
}
@@ -0,0 +1,125 @@
#!/usr/bin/python3
import os
import sys
import tempfile
import glob
import shutil
import shlex
import subprocess
import select
sys.path.append('/opt/lib/confluent/python')
import confluent.sortutil as sortutil
import confluent.client as client
def prep_outdir(node):
tmpdir = tempfile.mkdtemp()
for certfile in glob.glob('/var/lib/confluent/public/site/tls/*.pem'):
basename = os.path.basename(certfile)
destfile = os.path.join(tmpdir, basename)
shutil.copy2(certfile, destfile)
subprocess.check_call(shlex.split(f'confetty set /nodes/{node}/deployment/ident_image=create'))
shutil.copy2(f'/var/lib/confluent/private/identity_files/{node}.json', os.path.join(tmpdir, 'identity.json'))
return tmpdir
def exec_bfb_install(host, nodetorshim, bfbfile, installprocs, pipedesc, all, poller):
remotedir = subprocess.check_output(shlex.split(f'ssh {host} mktemp -d /tmp/bfb.XXXXXX')).decode().strip()
bfbbasename = os.path.basename(bfbfile)
subprocess.check_call(shlex.split(f'rsync -avz --info=progress2 {bfbfile} {host}:{remotedir}/{bfbbasename}'))
subprocess.check_call(shlex.split(f'rsync -avc --info=progress2 /opt/lib/confluent/osdeploy/bluefield/hostscripts/ {host}:{remotedir}/'))
for node in nodetorshim:
rshim = nodetorshim[node]
nodeoutdir = prep_outdir(node)
nodeprofile = subprocess.check_output(shlex.split(f'nodeattrib {node} deployment.pendingprofile')).decode().strip().split(':', 2)[2].strip()
shutil.copy2(f'/var/lib/confluent/public/os/{nodeprofile}/bfb.cfg.template', os.path.join(nodeoutdir, 'bfb.cfg.template'))
subprocess.check_call(shlex.split(f'rsync -avz {nodeoutdir}/ {host}:{remotedir}/{node}/'))
shutil.rmtree(nodeoutdir)
run_cmdv(node, shlex.split(f'ssh {host} sh /etc/confluent/functions confluentpython {remotedir}/bfb-autoinstall {node} {remotedir}/{bfbbasename} {rshim}'), all, poller, pipedesc)
def run_cmdv(node, cmdv, all, poller, pipedesc):
try:
nopen = subprocess.Popen(
cmdv, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError as e:
if e.errno == 2:
sys.stderr.write('{0}: Unable to find local executable file "{1}"\n'.format(node, cmdv[0]))
return
raise
pipedesc[nopen.stdout.fileno()] = {'node': node, 'popen': nopen,
'type': 'stdout', 'file': nopen.stdout}
pipedesc[nopen.stderr.fileno()] = {'node': node, 'popen': nopen,
'type': 'stderr', 'file': nopen.stderr}
all.add(nopen.stdout)
poller.register(nopen.stdout, select.EPOLLIN)
all.add(nopen.stderr)
poller.register(nopen.stderr, select.EPOLLIN)
if __name__ == '__main__':
if len(sys.argv) < 3:
print(f'Usage: {sys.argv[0]} <host> <bfbfile> <node1:rshim1> [<node2:rshim2> ...]')
sys.exit(1)
host = sys.argv[1]
bfbfile = sys.argv[2]
nodetorshim = {}
for arg in sys.argv[3:]:
node, rshim = arg.split(':')
nodetorshim[node] = rshim
installprocs = {}
pipedesc = {}
all = set()
poller = select.epoll()
exec_bfb_install(host, nodetorshim, bfbfile, installprocs, pipedesc, all, poller)
rdy = poller.poll(10)
pendingexecs = []
exitcode = 0
while all:
pernodeout = {}
for r in rdy:
r = r[0]
desc = pipedesc[r]
r = desc['file']
node = desc['node']
data = True
singlepoller = select.epoll()
singlepoller.register(r, select.EPOLLIN)
while data and singlepoller.poll(0):
data = r.readline()
if data:
if desc['type'] == 'stdout':
if node not in pernodeout:
pernodeout[node] = []
pernodeout[node].append(data)
else:
data = client.stringify(data)
sys.stderr.write('{0}: {1}'.format(node, data))
sys.stderr.flush()
else:
pop = desc['popen']
ret = pop.poll()
if ret is not None:
exitcode = exitcode | ret
all.discard(r)
poller.unregister(r)
r.close()
if desc['type'] == 'stdout' and pendingexecs:
node, cmdv = pendingexecs.popleft()
run_cmdv(node, cmdv, all, poller, pipedesc)
singlepoller.close()
for node in sortutil.natural_sort(pernodeout):
for line in pernodeout[node]:
line = client.stringify(line)
sys.stdout.write('{0}: {1}'.format(node, line))
sys.stdout.flush()
if all:
rdy = poller.poll(10)
+19 -4
View File
@@ -1,7 +1,11 @@
VERSION=`git describe|cut -d- -f 1`
NUMCOMMITS=`git describe|cut -d- -f 2`
if [ "$NUMCOMMITS" != "$VERSION" ]; then
VERSION=$VERSION.dev$NUMCOMMITS.g`git describe|cut -d- -f 3`
LASTNUM=$(echo $VERSION|rev|cut -d . -f 1|rev)
LASTNUM=$((LASTNUM+1))
FIRSTPART=$(echo $VERSION|rev|cut -d . -f 2- |rev)
VERSION=${FIRSTPART}.${LASTNUM}
VERSION=$VERSION~dev$NUMCOMMITS+`git describe|cut -d- -f 3`
fi
sed -e "s/#VERSION#/$VERSION/" confluent_osdeploy.spec.tmpl > confluent_osdeploy.spec
cd ..
@@ -11,13 +15,24 @@ mv confluent_osdeploy.tar.xz ~/rpmbuild/SOURCES/
cd -
mkdir -p el9bin/opt/confluent/bin
mkdir -p el9bin/stateless-bin
podman run --privileged --rm -v $(pwd)/utils:/buildutils -i -t fedorabuilder make -C /buildutils
podman run --privileged --rm -v $(pwd)/utils:/buildutils -i -t fedorabuild make -C /buildutils
cd utils
mv confluent_imginfo copernicus clortho autocons ../el9bin/opt/confluent/bin
mv start_root urlmount ../el9bin/stateless-bin/
cp confluent_imginfo copernicus clortho autocons ../el9bin/opt/confluent/bin
cp start_root urlmount ../el9bin/stateless-bin/
make clean
cd ..
mkdir -p el8bin/opt/confluent/bin
mkdir -p el8bin/stateless-bin
podman run --privileged --rm -v $(pwd)/utils:/buildutils -i -t el7build make -C /buildutils
cd utils
cp confluent_imginfo copernicus clortho autocons ../el8bin/opt/confluent/bin
cp start_root urlmount ../el8bin/stateless-bin/
make clean
cd ..
tar Jcvf confluent_el9bin.tar.xz el9bin/
tar Jcvf confluent_el8bin.tar.xz el8bin/
mv confluent_el8bin.tar.xz ~/rpmbuild/SOURCES/
mv confluent_el9bin.tar.xz ~/rpmbuild/SOURCES/
rm -rf el9bin
rm -rf el8bin
rpmbuild -ba confluent_osdeploy.spec
+38
View File
@@ -0,0 +1,38 @@
cd $(dirname $0)
VERSION=`git describe|cut -d- -f 1`
NUMCOMMITS=`git describe|cut -d- -f 2`
if [ "$NUMCOMMITS" != "$VERSION" ]; then
LASTNUM=$(echo $VERSION|rev|cut -d . -f 1|rev)
LASTNUM=$((LASTNUM+1))
FIRSTPART=$(echo $VERSION|rev|cut -d . -f 2- |rev)
VERSION=${FIRSTPART}.${LASTNUM}
VERSION=$VERSION~dev$NUMCOMMITS+`git describe|cut -d- -f 3`
fi
sed -e "s/#VERSION#/$VERSION/" confluent_osdeploy-aarch64.spec.tmpl > confluent_osdeploy-aarch64.spec
cd ..
cp ../LICENSE .
tar Jcvf confluent_osdeploy.tar.xz confluent_osdeploy
mv confluent_osdeploy.tar.xz ~/rpmbuild/SOURCES/
cd -
mkdir -p el9bin/opt/confluent/bin
mkdir -p el9bin/stateless-bin
mkdir -p el8bin/opt/confluent/bin
mkdir -p el8bin/stateless-bin
podman run --privileged --rm -v $(pwd)/utils:/buildutils -i -t el9builder make -C /buildutils
cd utils
mv confluent_imginfo copernicus clortho autocons ../el9bin/opt/confluent/bin
mv start_root urlmount ../el9bin/stateless-bin/
cd ..
podman run --privileged --rm -v $(pwd)/utils:/buildutils -i -t el8builder make -C /buildutils
cd utils
mv confluent_imginfo copernicus clortho autocons ../el8bin/opt/confluent/bin
mv start_root urlmount ../el8bin/stateless-bin/
cd ..
tar Jcvf confluent_el9bin.tar.xz el9bin/
tar Jcvf confluent_el8bin.tar.xz el8bin/
mv confluent_el8bin.tar.xz ~/rpmbuild/SOURCES/
mv confluent_el9bin.tar.xz ~/rpmbuild/SOURCES/
rm -rf el9bin
rm -rf el8bin
podman run --privileged --rm -v $HOME:/root el8builder rpmbuild -ba /root/confluent/confluent_osdeploy/confluent_osdeploy-aarch64.spec
@@ -3,6 +3,7 @@ try:
import http.client as client
except ImportError:
import httplib as client
import base64
import ctypes
import ctypes.util
import glob
@@ -14,6 +15,14 @@ import ssl
import sys
import struct
import time
import re
import hashlib
try:
import json
import hmac
except ImportError:
json = None
hmac = None
class InvalidApiKey(Exception):
pass
@@ -21,6 +30,10 @@ class InvalidApiKey(Exception):
def msg_align(len):
return (len + 3) & ~3
try:
_protoparm = ssl.PROTOCOL_TLS_CLIENT
except AttributeError:
_protoparm = ssl.PROTOCOL_SSLv23
cryptname = ctypes.util.find_library('crypt')
if not cryptname:
if os.path.exists('/lib64/libcrypt.so.2') or os.path.exists('/usr/lib64/libcrypt.so.2'):
@@ -34,40 +47,115 @@ c_crypt.restype = ctypes.c_char_p
def get_my_addresses():
nlhdrsz = struct.calcsize('IHHII')
ifaddrsz = struct.calcsize('BBBBI')
# RTM_GETADDR = 22
# nlmsghdr struct: u32 len, u16 type, u16 flags, u32 seq, u32 pid
nlhdr = struct.pack('IHHII', nlhdrsz + ifaddrsz, 22, 0x301, 0, 0)
# ifaddrmsg struct: u8 family, u8 prefixlen, u8 flags, u8 scope, u32 index
ifaddrmsg = struct.pack('BBBBI', 0, 0, 0, 0, 0)
s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
s.bind((0, 0))
s.sendall(nlhdr + ifaddrmsg)
addrs = []
while True:
pdata = s.recv(65536)
v = memoryview(pdata)
if struct.unpack('H', v[4:6])[0] == 3: # netlink done message
break
while len(v):
length, typ = struct.unpack('IH', v[:6])
if typ == 20:
fam, plen, _, scope, ridx = struct.unpack('BBBBI', v[nlhdrsz:nlhdrsz+ifaddrsz])
if scope in (253, 0):
rta = v[nlhdrsz+ifaddrsz:length]
while len(rta):
rtalen, rtatyp = struct.unpack('HH', rta[:4])
if rtalen < 4:
break
if rtatyp == 1:
addrs.append((fam, rta[4:rtalen], plen, ridx))
rta = rta[msg_align(rtalen):]
v = v[msg_align(length):]
for ifa in get_ifaddrs():
if ifa[0] == 'ip':
addrs.append((ifa[1], ifa[2], ifa[3]))
return addrs
def get_mac_addresses():
macs = []
for ifa in get_ifaddrs():
if ifa[0] == 'ETHER':
macs.append((ifa[1], ifa[2]))
return macs
def scan_confluents():
def get_ifaddrs():
class sockaddr(ctypes.Structure):
_fields_ = [
('sa_family', ctypes.c_uint16),
('sa_data', ctypes.c_ubyte * 14),
]
class sockaddr_in(ctypes.Structure):
_fields_ = [
('sin_family', ctypes.c_uint16),
('sin_port', ctypes.c_uint16),
('sin_addr', ctypes.c_ubyte * 4),
('sin_zero', ctypes.c_ubyte * 8),
]
class sockaddr_in6(ctypes.Structure):
_fields_ = [
('sin6_family', ctypes.c_uint16),
('sin6_port', ctypes.c_uint16),
('sin6_flowinfo', ctypes.c_uint32),
('sin6_addr', ctypes.c_ubyte * 16),
('sin6_scope_id', ctypes.c_uint32),
]
class sockaddr_ll(ctypes.Structure):
_fields_ = [
('sll_family', ctypes.c_uint16),
('sll_protocol', ctypes.c_uint16),
('sll_ifindex', ctypes.c_int32),
('sll_hatype', ctypes.c_uint16),
('sll_pkttype', ctypes.c_uint8),
('sll_halen', ctypes.c_uint8),
('sll_addr', ctypes.c_ubyte * 8),
]
class ifaddrs(ctypes.Structure):
pass
ifaddrs._fields_ = [
('ifa_next', ctypes.POINTER(ifaddrs)),
('ifa_name', ctypes.c_char_p),
('ifa_flags', ctypes.c_uint),
('ifa_addr', ctypes.POINTER(sockaddr)),
('ifa_netmask', ctypes.POINTER(sockaddr)),
('ifa_ifu', ctypes.POINTER(sockaddr)),
('ifa_data', ctypes.c_void_p),
]
libc = ctypes.CDLL(ctypes.util.find_library('c'))
libc.getifaddrs.argtypes = [ctypes.POINTER(ctypes.POINTER(ifaddrs))]
libc.getifaddrs.restype = ctypes.c_int
libc.freeifaddrs.argtypes = [ctypes.POINTER(ifaddrs)]
libc.freeifaddrs.restype = None
ifap = ctypes.POINTER(ifaddrs)()
result = libc.getifaddrs(ctypes.pointer(ifap))
if result != 0:
return []
addresses = []
ifa = ifap
try:
while ifa:
if ifa.contents.ifa_addr:
family = ifa.contents.ifa_addr.contents.sa_family
name = ifa.contents.ifa_name.decode('utf-8') if ifa.contents.ifa_name else None
if family in (socket.AF_INET, socket.AF_INET6):
# skip loopback and non-multicast interfaces
if ifa.contents.ifa_flags & 8 or not ifa.contents.ifa_flags & 0x1000:
ifa = ifa.contents.ifa_next
continue
if family == socket.AF_INET:
addr_ptr = ctypes.cast(ifa.contents.ifa_addr, ctypes.POINTER(sockaddr_in))
addr_bytes = bytes(addr_ptr.contents.sin_addr)
if_index = socket.if_nametoindex(name) if name else 0
addresses.append(('ip', family, addr_bytes, if_index))
elif family == socket.AF_INET6:
addr_ptr = ctypes.cast(ifa.contents.ifa_addr, ctypes.POINTER(sockaddr_in6))
addr_bytes = bytes(addr_ptr.contents.sin6_addr)
scope_id = addr_ptr.contents.sin6_scope_id
addresses.append(('ip', family, addr_bytes, scope_id))
elif family == socket.AF_PACKET:
addr_ptr = ctypes.cast(ifa.contents.ifa_addr, ctypes.POINTER(sockaddr_ll))
halen = addr_ptr.contents.sll_halen
if addr_ptr.contents.sll_hatype in (1, 32) and halen > 0: # ARPHRD_ETHER or ARPHRD_INFINIBAND
if addr_ptr.contents.sll_hatype == 1 and addr_ptr.contents.sll_addr[0] & 2: # skip locally administered MACs
ifa = ifa.contents.ifa_next
continue
mac_bytes = bytes(addr_ptr.contents.sll_addr[:halen])
macaddr = ':'.join('{:02x}'.format(b) for b in mac_bytes)
addresses.append(('ETHER', name, macaddr))
ifa = ifa.contents.ifa_next
finally:
libc.freeifaddrs(ifap)
return addresses
def scan_confluents(confuuid=None):
srvs = {}
s6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
@@ -79,18 +167,24 @@ def scan_confluents():
s4.bind(('0.0.0.0', 1900))
doneidxs = set([])
msg = 'M-SEARCH * HTTP/1.1\r\nST: urn:xcat.org:service:confluent:'
with open('/etc/confluent/confluent.deploycfg') as dcfg:
for line in dcfg.read().split('\n'):
if line.startswith('confluent_uuid:'):
confluentuuid = line.split(': ')[1]
msg += '/confluentuuid=' + confluentuuid
break
with open('/sys/devices/virtual/dmi/id/product_uuid') as uuidin:
msg += '/uuid=' + uuidin.read().strip()
for addrf in glob.glob('/sys/class/net/*/address'):
with open(addrf) as addrin:
hwaddr = addrin.read().strip()
msg += '/mac=' + hwaddr
if not confuuid and os.path.exists('/etc/confluent/confluent.deploycfg'):
with open('/etc/confluent/confluent.deploycfg') as dcfg:
for line in dcfg.read().split('\n'):
if line.startswith('confluent_uuid:'):
confluentuuid = line.split(': ')[1]
msg += '/confluentuuid=' + confluentuuid
break
if not confuuid and os.path.exists('/confluent_uuid'):
with open('/confluent_uuid') as cuuidin:
confluentuuid = cuuidin.read().strip()
msg += '/confluentuuid=' + confluentuuid
try:
with open('/sys/devices/virtual/dmi/id/product_uuid') as uuidin:
msg += '/uuid=' + uuidin.read().strip()
except Exception:
pass
for iface, hwaddr in get_mac_addresses():
msg += '/mac=' + hwaddr
msg = msg.encode('utf8')
for addr in get_my_addresses():
if addr[0] == socket.AF_INET6:
@@ -118,6 +212,7 @@ def scan_confluents():
srvlist = []
if r:
r = r[0]
nodename = None
while r:
for s in r:
(rsp, peer) = s.recvfrom(9000)
@@ -125,6 +220,7 @@ def scan_confluents():
current = None
for line in rsp:
if line.startswith(b'NODENAME: '):
nodename = line.replace(b'NODENAME: ', b'').strip().decode('utf8')
current = {}
elif line.startswith(b'DEFAULTNET: 1'):
current['isdefault'] = True
@@ -132,21 +228,41 @@ def scan_confluents():
current['mgtiface'] = line.replace(b'MGTIFACE: ', b'').strip().decode('utf8')
if len(peer) > 2:
current['myidx'] = peer[-1]
srvs[peer[0]] = current
srvlist.append(peer[0])
currip = peer[0]
if currip.startswith('fe80::') and '%' not in currip:
currip = '{0}%{1}'.format(currip, peer[-1])
srvs[currip] = current
if currip not in srvlist:
srvlist.append(currip)
r = select.select((s4, s6), (), (), 2)
if r:
r = r[0]
if not os.path.exists('/etc/confluent/confluent.info'):
with open('/etc/confluent/confluent.info', 'w+') as cinfo:
if nodename:
cinfo.write('NODENAME: {0}\n'.format(nodename))
for srv in srvlist:
cinfo.write('MANAGER: {0}\n'.format(srv))
return srvlist, srvs
def get_net_apikey(nodename, mgr):
def get_net_apikey(nodename, mgr, hmackey=None, confuuid=None):
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./'
newpass = ''.join([alpha[x >> 2] for x in bytearray(os.urandom(32))])
salt = '$5$' + ''.join([alpha[x >> 2] for x in bytearray(os.urandom(8))])
newpass = newpass.encode('utf8')
salt = salt.encode('utf8')
crypted = c_crypt(newpass, salt)
if hmackey:
hmacvalue = hmac.new(hmackey.encode('utf8'), crypted, hashlib.sha256).digest()
hmacvalue = base64.b64encode(hmacvalue).decode('utf8')
client = HTTPSClient(host=mgr, phmac=hmacvalue, nodename=nodename, confuuid=confuuid)
try:
status, rsp = client.grab_url_with_status('/confluent-api/self/registerapikey', data=crypted, returnrsp=True)
if status == 200:
return newpass.decode('utf8')
except Exception:
pass
for addrinfo in socket.getaddrinfo(mgr, 13001, 0, socket.SOCK_STREAM):
try:
clisock = socket.socket(addrinfo[0], addrinfo[1])
@@ -156,6 +272,7 @@ def get_net_apikey(nodename, mgr):
else:
cliaddr = ('::', 302)
clisock.bind(cliaddr)
clisock.settimeout(1)
clisock.connect(addrinfo[-1])
rsp = clisock.recv(8)
if rsp != b'\xc2\xd1-\xa8\x80\xd8j\xba':
@@ -183,7 +300,7 @@ def get_net_apikey(nodename, mgr):
return ''
def get_apikey(nodename, hosts, errout=None):
def get_apikey(nodename, hosts, errout=None, hmackey=None, confuuid=None):
apikey = ""
if os.path.exists('/etc/confluent/confluent.apikey'):
apikey = open('/etc/confluent/confluent.apikey').read().strip()
@@ -192,16 +309,16 @@ def get_apikey(nodename, hosts, errout=None):
while not apikey:
for host in hosts:
try:
apikey = get_net_apikey(nodename, host)
apikey = get_net_apikey(nodename, host, hmackey=hmackey, confuuid=confuuid)
except OSError:
apikey = None
if apikey:
break
else:
srvlist, _ = scan_confluents()
srvlist, _ = scan_confluents(confuuid=confuuid)
for host in srvlist:
try:
apikey = get_net_apikey(nodename, host)
apikey = get_net_apikey(nodename, host, hmackey=hmackey, confuuid=confuuid)
except OSError:
apikey = None
if apikey:
@@ -219,45 +336,66 @@ def get_apikey(nodename, hosts, errout=None):
return apikey
class HTTPSClient(client.HTTPConnection, object):
def __init__(self, usejson=False, port=443, host=None, errout=None):
def __init__(self, usejson=False, port=443, host=None, errout=None, phmac=None, checkonly=False, hmackey=None, nodename=None, confuuid=None):
self.ignorehosts = set([])
self.phmac = phmac
self.hmackey = hmackey
self.confuuid = confuuid
self.errout = None
self.stdheaders = {}
if nodename:
self.stdheaders['CONFLUENT_NODENAME'] = nodename
if errout:
self.errout = open(errout, 'w')
self.errout.flush()
self.stdheaders = {}
mgtiface = None
if usejson:
self.stdheaders['ACCEPT'] = 'application/json'
if host:
self.hosts = [host]
with open('/etc/confluent/confluent.info') as cinfo:
info = cinfo.read().split('\n')
for line in info:
if line.startswith('NODENAME:'):
node = line.split(' ')[1]
self.stdheaders['CONFLUENT_NODENAME'] = node
if not nodename:
with open('/etc/confluent/confluent.info') as cinfo:
info = cinfo.read().split('\n')
for line in info:
if line.startswith('NODENAME:'):
nodename = line.split(' ')[1]
self.stdheaders['CONFLUENT_NODENAME'] = nodename
else:
self.hosts = []
info = open('/etc/confluent/confluent.info').read().split('\n')
try:
info = open('/etc/confluent/confluent.info').read().split('\n')
except Exception:
info = []
havedefault = '0'
plainhost = ''
for line in info:
host = ''
if line.startswith('NODENAME:'):
node = line.split(' ')[1]
self.stdheaders['CONFLUENT_NODENAME'] = node
nodename = line.split(' ')[1]
self.stdheaders['CONFLUENT_NODENAME'] = nodename
if line.startswith('MANAGER:') and not host:
host = line.split(' ')[1]
self.hosts.append(host)
if not plainhost:
plainhost = host
if line.startswith('EXTMGRINFO:'):
extinfo = line.split(' ')[1]
extinfo = extinfo.split('|')
if not mgtiface:
host, mgtiface, havedefault = extinfo[:3]
if havedefault == '0' and extinfo[2] == '1':
host, mgtiface, havedefault = extinfo[:3]
if '%' in host:
ifidx = host.split('%', 1)[1]
with open('/tmp/confluent.ifidx', 'w+') as ifout:
ifout.write(ifidx)
self.hosts.append(host)
if '%' in host:
ifidx = host.split('%', 1)[1]
with open('/tmp/confluent.ifidx', 'w+') as ifout:
ifout.write(ifidx)
if not mgtiface:
host, mgtiface, havedefault = extinfo[:3]
if host:
if havedefault == '0':
if '%' in host:
ifidx = host.split('%', 1)[1]
with open('/tmp/confluent.ifidx', 'w+') as ifout:
ifout.write(ifidx)
self.hosts.append(host)
try:
info = open('/etc/confluent/confluent.deploycfg').read().split('\n')
except Exception:
@@ -266,12 +404,17 @@ class HTTPSClient(client.HTTPConnection, object):
for line in info:
if line.startswith('deploy_server: ') or line.startswith('deploy_server_v6: '):
self.hosts.append(line.split(': ', 1)[1])
self.stdheaders['CONFLUENT_APIKEY'] = get_apikey(node, self.hosts, errout=self.errout)
if plainhost and not self.hosts:
self.hosts.append(plainhost)
if self.phmac:
self.stdheaders['CONFLUENT_CRYPTHMAC'] = self.phmac
elif not checkonly:
self.stdheaders['CONFLUENT_APIKEY'] = get_apikey(nodename, self.hosts, errout=self.errout, hmackey=hmackey, confuuid=self.confuuid)
if mgtiface:
self.stdheaders['CONFLUENT_MGTIFACE'] = mgtiface
self.port = port
self.host = None
self.node = node
self.node = nodename
host = self.check_connections()
client.HTTPConnection.__init__(self, host, port)
self.connect()
@@ -283,23 +426,35 @@ class HTTPSClient(client.HTTPConnection, object):
def check_connections(self):
foundsrv = None
hosts = self.hosts
ctx = ssl.SSLContext(_protoparm)
ctx.load_verify_locations('/etc/confluent/ca.pem')
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.check_hostname = True
for timeo in (0.1, 5):
for host in hosts:
if host in self.ignorehosts:
continue
try:
addrinf = socket.getaddrinfo(host, self.port)[0]
psock = socket.socket(addrinf[0])
psock.settimeout(timeo)
psock.connect(addrinf[4])
chost = host.split('%', 1)[0]
ctx.wrap_socket(psock, server_hostname=chost)
foundsrv = host
psock.close()
break
except OSError:
except (OSError, socket.error):
continue
except ssl.SSLError:
continue
except ssl.CertificateError:
continue
else:
continue
break
if not foundsrv:
srvlist, srvs = scan_confluents()
srvlist, srvs = scan_confluents(self.confuuid)
hosts = []
for srv in srvlist:
if srvs[srv].get('isdefault', False):
@@ -321,11 +476,12 @@ class HTTPSClient(client.HTTPConnection, object):
raise Exception('Unable to reach any hosts')
return foundsrv
def connect(self):
def connect(self, tries=3):
addrinf = socket.getaddrinfo(self.host, self.port)[0]
psock = socket.socket(addrinf[0])
psock.settimeout(15)
psock.connect(addrinf[4])
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx = ssl.SSLContext(_protoparm)
ctx.load_verify_locations('/etc/confluent/ca.pem')
host = self.host.split('%', 1)[0]
if '[' not in host and ':' in host:
@@ -343,6 +499,10 @@ class HTTPSClient(client.HTTPConnection, object):
self.errout.write(errmsg)
self.errout.flush()
sys.exit(1)
except socket.timeout:
if not tries:
raise
return self.connect(tries=tries-1)
def grab_url(self, url, data=None, returnrsp=False):
return self.grab_url_with_status(url, data, returnrsp)[1]
@@ -368,11 +528,101 @@ class HTTPSClient(client.HTTPConnection, object):
with open('/etc/confluent/confluent.apikey', 'w+') as akfile:
akfile.write('')
self.stdheaders['CONFLUENT_APIKEY'] = get_apikey(
self.node, [self.host], errout=self.errout)
self.node, [self.host], errout=self.errout, hmackey=self.hmackey, confuuid=self.confuuid)
if rsp.status == 503: # confluent is down, but the server running confluent is otherwise up
authed = False
self.ignorehosts.add(self.host)
host = self.check_connections()
client.HTTPConnection.__init__(self, host, self.port)
raise Exception(rsp.read())
def get_current_vmnic_vswitch():
uplinkmatch = re.compile(r'^\s*Uplinks:\s*(.*)')
switchmatch = re.compile(r'^\s*Name:\s*(.*)')
vswinfo = subprocess.check_output(['localcli', 'network', 'vswitch', 'standard', 'list']).decode()
vmnic = None
vswitch_name = None
for info in vswinfo.split('\n'):
name_match = switchmatch.match(info)
if name_match:
vswitch_name = name_match.group(1).strip()
upinfo = uplinkmatch.match(info)
if upinfo:
vmnic = upinfo.group(1).strip()
if vmnic and 'vusb0' not in vmnic:
return vswitch_name, vmnic
return vswitch_name, vmnic
def get_available_nics():
nicinfo = subprocess.check_output(['localcli', 'network', 'nic', 'list']).decode('utf8').split('\n')
available_nics = {}
# Skip headers and separators
parsing_started = False
for line in nicinfo:
if re.match(r'^-+', line):
parsing_started = True
continue
if not parsing_started or not line.strip():
continue
parts = re.split(r'\s{2,}', line.strip())
if len(parts) >= 5:
nic_name = parts[0]
nic_status = parts[4] # "Link Status" is the 5th field
available_nics[nic_name] = nic_status
return available_nics
def is_esxi():
return os.path.isdir("/etc/vmware")
def fix_vswitch():
if is_esxi():
start_time = time.time()
while True:
current_vswitch, current_vmnic = get_current_vmnic_vswitch()
if current_vswitch is None:
raise RuntimeError("Panic: current vswitch is None")
if current_vmnic is None:
raise RuntimeError("Panic: current vmnic is None")
available_nics = get_available_nics()
if current_vmnic and available_nics.get(current_vmnic) == 'Up':
break
new_vmnic = next((nic for nic, status in available_nics.items() if status == 'Up'), None)
if new_vmnic and new_vmnic != current_vmnic:
subprocess.check_call(['localcli', 'network', 'vswitch', 'standard', 'uplink', 'remove',
'--uplink-name', current_vmnic, '--vswitch-name', current_vswitch])
subprocess.check_call(['localcli', 'network', 'vswitch', 'standard', 'uplink', 'add',
'--uplink-name', new_vmnic, '--vswitch-name', current_vswitch])
elif not new_vmnic:
if time.time() - start_time > 300:
break
time.sleep(5)
time.sleep(5)
if __name__ == '__main__':
data = None
if '-f' in sys.argv:
try:
fix_vswitch()
except Exception as e:
print("fix_vswitch() error: {}".format(e))
sys.argv.remove('-f')
sys.exit(0)
usejson = False
if '-j' in sys.argv:
usejson = True
@@ -403,22 +653,57 @@ if __name__ == '__main__':
errout = sys.argv.pop(errout)
except ValueError:
errout = None
try:
phmac = sys.argv.index('-p')
sys.argv.pop(phmac)
phmac = sys.argv.pop(phmac)
with open(phmac, 'r') as hmacin:
phmac = hmacin.read()
except ValueError:
phmac = None
try:
identfile = sys.argv.index('-i')
sys.argv.pop(identfile)
identfile = sys.argv.pop(identfile)
with open(identfile) as idin:
data = idin.read()
identinfo = json.loads(data)
nodename = identinfo.get('nodename', None)
hmackey = identinfo.get('apitoken', None)
confuuid = identinfo.get('confluent_uuid', None)
except ValueError:
hmackey = None
nodename = None
confuuid = None
try:
checkonly = False
idxit = sys.argv.index('-c')
sys.argv.pop(idxit)
checkonly = True
except Exception:
pass
if len(sys.argv) > 2 and os.path.exists(sys.argv[-1]):
data = open(sys.argv[-1]).read()
if outbin:
with open(outbin, 'ab+') as outf:
reader = HTTPSClient(usejson=usejson, errout=errout).grab_url(
reader = HTTPSClient(usejson=usejson, errout=errout, hmackey=hmackey, nodename=nodename, confuuid=confuuid).grab_url(
sys.argv[1], data, returnrsp=True)
chunk = reader.read(16384)
while chunk:
outf.write(chunk)
chunk = reader.read(16384)
sys.exit(0)
mclient = HTTPSClient(usejson, errout=errout, phmac=phmac, checkonly=checkonly, hmackey=hmackey, nodename=nodename, confuuid=confuuid)
if waitfor:
client = HTTPSClient(usejson, errout=errout)
status = 201
while status != waitfor:
status, rsp = client.grab_url_with_status(sys.argv[1], data)
status, rsp = mclient.grab_url_with_status(sys.argv[1], data)
sys.stdout.write(rsp.decode())
elif checkonly:
sys.stdout.write(mclient.check_connections())
else:
sys.stdout.write(HTTPSClient(usejson, errout=errout).grab_url(sys.argv[1], data).decode())
try:
sys.stdout.buffer.write(mclient.grab_url(sys.argv[1], data))
except AttributeError:
sys.stdout.write(mclient.grab_url(sys.argv[1], data))
@@ -0,0 +1,145 @@
#!/usr/bin/python3
# This script evaluates whether firmware redirection is likely. It uses three cues:
# - Does the system offer up SPCR? This would indicate that the firmware is doing serial output.
# Otherwise, there's no indication that the firmware cares about serial console.
# - Is the system EFI? BIOS implementations may not intercept text draw calls after POST exit,
# thus even when BIOS tells us serial port is in use, it may not be doing anything when
# grub would be running
# - Is the serial port connected? In the event that firmware indicates serial port, but
# serial port is not reporting DCD, then it doesn't look like a comfortable enough scenario
import fcntl
import glob
import os
import os.path
import struct
import subprocess
import termios
import platform
addrtoname = {
0x3f8: '/dev/ttyS0',
0x2f8: '/dev/ttyS1',
0x3e8: '/dev/ttyS2',
0x2e8: '/dev/ttyS3',
}
speedmap = {
0: None,
3: 9600,
4: 19200,
6: 57600,
7: 115200,
}
termiobaud = {
9600: termios.B9600,
19200: termios.B19200,
57600: termios.B57600,
115200: termios.B115200,
}
def deserialize_grub_rh():
if 'console=ttyS' in open('/proc/cmdline').read():
return None # User manually indicated serial config
# they own the grub behavior too for now
grublines = []
with open('/etc/default/grub') as grubin:
grublines = grubin.read().split('\n')
with open('/etc/default/grub', 'w') as grubout:
for grubline in grublines:
if grubline.startswith('GRUB_TERMINAL'):
grubline = grubline.replace('serial ', '')
grubout.write(grubline + '\n')
subprocess.check_call(['grub2-mkconfig', '-o', '/boot/grub2/grub.cfg'])
def fixup_ubuntu_grub_serial():
# Ubuntu aggressively tries to graphics up
# grub. We will counter that for serial
# They also aggressively hide UI and
# block ability to interject. We will
# compromise and lean on nodeboot <node> setup
# as a means to give someone reasonable shot at
# the short timeout
with open('/etc/default/grub') as grubin:
grublines = grubin.read().split('\n')
with open('/etc/default/grub', 'w') as grubout:
for grubline in grublines:
if grubline.startswith('GRUB_TIMEOUT_STYLE=hidden'):
grubline = 'GRUB_TIMEOUT_STYLE=menu'
elif grubline.startswith('GRUB_TIMEOUT=0'):
grubline = 'GRUB_TIMEOUT=2'
elif grubline.startswith('#GRUB_TERMINAL=console'):
grubline = grubline.replace('#', '')
grubout.write(grubline + '\n')
subprocess.check_call(['update-grub'])
def get_spcr_config():
if not os.path.exists('/sys/firmware/acpi/tables/SPCR'):
return None
spcr = open("/sys/firmware/acpi/tables/SPCR", "rb")
spcr = bytearray(spcr.read())
if spcr[8] != 2 or spcr[36] != 0 or spcr[40] != 1:
return None
address = struct.unpack('<Q', spcr[44:52])[0]
tty = None
try:
tty = addrtoname[address]
except KeyError:
return None
retval = { 'tty': tty }
try:
retval['speed'] = speedmap[spcr[58]]
except KeyError:
return None
if retval['speed']:
ttyf = os.open(tty, os.O_RDWR | os.O_NOCTTY)
currattr = termios.tcgetattr(ttyf)
currattr[4:6] = [0, termiobaud[retval['speed']]]
termios.tcsetattr(ttyf, termios.TCSANOW, currattr)
return retval
def get_serial_config():
if platform.machine() != 'x86_64':
return None # Trust non-x86 to do the right thing
if not os.path.exists('/sys/firmware/efi'):
return None # BIOS might fail at grub output, defer to stock OS behavior
retval = get_spcr_config()
if retval:
return retval
firstfound = None
numpossible = 0
numconnected = 0
for serdev in glob.glob('/dev/ttyS*'):
ttyf = os.open(serdev, os.O_RDWR | os.O_NOCTTY)
try:
statusreg = fcntl.ioctl(ttyf, termios.TIOCMGET, '\x00\x00\x00\x00')
numpossible += 1
if not firstfound:
firstfound = serdev
except Exception:
continue
finally:
os.close(ttyf)
if struct.unpack('<I', statusreg)[0] & termios.TIOCM_CAR:
numconnected += 1
firstfound = serdev
if numpossible == 1 or numconnected == 1:
return { 'tty': firstfound, 'speed': 115200 }
def main():
autoconscfg = get_serial_config()
if not autoconscfg:
return
if os.path.exists('/etc/redhat-release'): # redhat family
deserialize_grub_rh()
elif os.path.exists('/etc/os-release'):
with open('/etc/os-release') as osr:
if 'Ubuntu' in osr.read():
fixup_ubuntu_grub_serial()
if __name__ == '__main__':
main()
@@ -8,6 +8,10 @@ import sys
import time
import shlex
import subprocess
try:
import yaml
except ImportError:
pass
try:
from importlib.machinery import SourceFileLoader
def load_source(mod, path):
@@ -25,6 +29,8 @@ def add_lla(iface, mac):
initbyte = int(pieces[0], 16) ^ 2
lla = 'fe80::{0:x}{1}:{2}ff:fe{3}:{4}{5}/64'.format(initbyte, pieces[1], pieces[2], pieces[3], pieces[4], pieces[5])
try:
with open('/proc/sys/net/ipv6/conf/{0}/disable_ipv6'.format(iface), 'w') as setin:
setin.write('0')
subprocess.check_call(['ip', 'addr', 'add', 'dev', iface, lla, 'scope', 'link'])
except Exception:
return None
@@ -74,14 +80,18 @@ def await_tentative():
time.sleep(1)
def map_idx_to_name():
map = {}
map_dict = {}
devtype = {}
prevdev = None
for line in subprocess.check_output(['ip', 'l']).decode('utf8').splitlines():
if line.startswith(' ') and 'link/' in line:
typ = line.split()[0].split('/')[1]
devtype[prevdev] = typ if type != 'ether' else 'ethernet'
if line.startswith(' '):
if 'link/' in line and prevdev and prevdev not in devtype:
for word in line.split():
if word.startswith('link/'):
typ = word.split('/')[1]
devtype[prevdev] = typ if typ != 'ether' else 'ethernet'
break # Stop detection after the first type hit
continue
idx, iface, rst = line.split(':', 2)
prevdev = iface.strip()
@@ -93,9 +103,8 @@ def map_idx_to_name():
pass
idx = int(idx)
iface = iface.strip()
map[idx] = iface
return map, devtype
map_dict[idx] = iface
return map_dict, devtype
def get_interface_name(iname, settings):
explicitname = settings.get('interface_names', None)
@@ -105,6 +114,181 @@ def get_interface_name(iname, settings):
return iname
return None
class NetplanManager(object):
def __init__(self, deploycfg):
self.cfgbydev = {}
self.cfgbybond = {}
self.read_connections()
self.deploycfg = deploycfg
self.teamidx = 0
def read_connections(self):
for plan in glob.glob('/etc/netplan/*.y*ml'):
with open(plan) as planfile:
planinfo = yaml.safe_load(planfile)
if not planinfo:
continue
nicinfo = planinfo.get('network', {}).get('ethernets', {})
bondinfo = planinfo.get('network', {}).get('bonds', {})
for currinfo in (nicinfo, bondinfo):
currcfg = self.cfgbydev if currinfo is nicinfo else self.cfgbybond
for devname in currinfo:
if devname == 'lo':
continue
if 'gateway4' in currinfo[devname]:
# normalize deprecated syntax on read in
gw4 = currinfo[devname]['gateway4']
del currinfo[devname]['gateway4']
routeinfo = currinfo[devname].get('routes', [])
for ri in routeinfo:
if ri.get('via', None) == gw4 and ri.get('to', None) in ('default', '0.0.0.0/0', '0/0'):
break
else:
routeinfo.append({
'to': 'default',
'via': gw4
})
currinfo[devname]['routes'] = routeinfo
currcfg[devname] = currinfo[devname]
def apply_configuration(self, cfg):
devnames = cfg['interfaces']
if len(devnames) > 1:
teammode = cfg['settings'].get('team_mode', None)
if not teammode:
sys.stderr.write("Warning, multiple interfaces ({0}) without a team_mode, skipping setup\n".format(','.join(devnames)))
return
if teammode == 'lacp':
teammode = '802.3ad'
elif teammode == 'activebackup':
teammode = 'active-backup'
for currdev in self.cfgbybond:
for iface in self.cfgbybond[currdev].get('interfaces', []):
if iface in devnames:
break
else:
continue
else:
continue
# this bond is identified as matching
self.cfgbybond[currdev]['interfaces'] = list(devnames)
self.cfgbybond[currdev]['parameters']['mode'] = teammode
devnames = [currdev]
break
# no current bond, make a new one
connname = cfg['settings'].get('connection_name', None)
if not connname:
connname = 'bond{0}'.format(self.teamidx)
while connname in self.cfgbybond:
self.teamidx += 1
connname = 'bond{0}'.format(self.teamidx)
self.cfgbybond[connname] = {'interfaces': list(devnames), 'parameters': {'mode': teammode, 'mii-monitor-interval': 100}}
devnames = [connname]
stgs = cfg['settings']
needcfgapply = False
for devname in devnames:
needcfgwrite = False
# ipv6_method missing at uconn...
if stgs.get('ipv6_method', None) == 'static':
curraddr = stgs['ipv6_address']
currips = self.getcfgarrpath([devname, 'addresses'])
if curraddr not in currips:
needcfgwrite = True
currips.append(curraddr)
if stgs.get('ipv4_method', None) == 'static':
curraddr = stgs['ipv4_address']
currips = self.getcfgarrpath([devname, 'addresses'])
if curraddr not in currips:
needcfgwrite = True
currips.append(curraddr)
if stgs.get('mtu', None):
devdict = self.getcfgarrpath([devname])
devdict['mtu'] = int(stgs['mtu'])
gws = []
gws.append(stgs.get('ipv4_gateway', None))
gws.append(stgs.get('ipv6_gateway', None))
for gwaddr in gws:
if gwaddr and gwaddr != '0.0.0.0':
cfgroutes = self.getcfgarrpath([devname, 'routes'])
for rinfo in cfgroutes:
if rinfo.get('via', None) == gwaddr:
break
else:
needcfgwrite = True
cfgroutes.append({'via': gwaddr, 'to': 'default'})
dnsips = self.deploycfg.get('nameservers', [])
dnsdomain = self.deploycfg.get('dnsdomain', '')
if dnsips:
currdnsips = self.getcfgarrpath([devname, 'nameservers', 'addresses'])
for dnsip in dnsips:
if dnsip and dnsip not in currdnsips:
needcfgwrite = True
currdnsips.append(dnsip)
if dnsdomain:
currdnsdomain = self.getcfgarrpath([devname, 'nameservers', 'search'])
if dnsdomain not in currdnsdomain:
needcfgwrite = True
currdnsdomain.append(dnsdomain)
prune_from_cloudinit = []
if needcfgwrite:
needcfgapply = True
oumask = os.umask(0o77)
if devname in self.cfgbydev:
prune_from_cloudinit.append(devname)
newcfg = {'network': {'version': 2, 'ethernets': {devname: self.cfgbydev[devname]}}}
cfgfile = '/etc/netplan/10-{0}-confluentcfg.yaml'.format(devname)
elif devname in self.cfgbybond:
newcfg = {'network': {'version': 2, 'bonds': {devname: self.cfgbybond[devname]}}}
for iface in newcfg['network']['bonds'][devname]['interfaces']:
prune_from_cloudinit.append(iface)
with open('/etc/netplan/10-{0}-confluentcfg.yaml'.format(iface), 'w') as planout:
planout.write(yaml.dump({'network': {'version': 2, 'ethernets': {iface: {'dhcp4': False}}}}))
cfgfile = '/etc/netplan/30-{0}-confluentcfg.yaml'.format(devname)
with open(cfgfile, 'w') as planout:
planout.write(yaml.dump(newcfg))
os.umask(oumask)
if prune_from_cloudinit:
prunecfgs = ['/etc/netplan/00-installer-config.yaml',
'/etc/netplan/50-cloud-init.yaml.dist-subiquity',
'/etc/netplan/50-cloud-init.yaml']
prunecfgs.extend(glob.glob('/etc/cloud/cloud.cfg.d/*.cfg'))
for defcfg in prunecfgs:
if not os.path.exists(defcfg):
continue
with open(defcfg, 'r') as cloudinit:
cloudinfo = yaml.safe_load(cloudinit)
if 'network' not in cloudinfo:
continue
for clouddev in list(cloudinfo.get('network', {}).get('ethernets', {})):
if clouddev in prune_from_cloudinit:
del cloudinfo['network']['ethernets'][clouddev]
if not cloudinfo['network'].get('ethernets', {}):
os.remove(defcfg)
if '/etc/cloud/cloud.cfg.d/' in defcfg:
# need to also change datasource, probably
if os.path.exists('/var/lib/cloud/instances/iid-datasource-none/network-config.json'):
os.remove('/var/lib/cloud/instances/iid-datasource-none/network-config.json')
else:
oumask = os.umask(0o77)
with open(defcfg, 'w') as cloudinit:
cloudinit.write(yaml.dump(cloudinfo))
os.umask(oumask)
if needcfgapply:
subprocess.check_call(['netplan', 'generate'])
subprocess.call(['netplan', 'apply'])
def getcfgarrpath(self, devpath):
currptr = self.cfgbybond if devpath[0] in self.cfgbybond else self.cfgbydev
for k in devpath[:-1]:
if k not in currptr:
currptr[k] = {}
currptr = currptr[k]
if devpath[-1] not in currptr:
currptr[devpath[-1]] = []
return currptr[devpath[-1]]
class WickedManager(object):
def __init__(self):
self.teamidx = 0
@@ -120,7 +304,11 @@ class WickedManager(object):
self.cfgbydev[devname] = currcfg
for cfg in open(ifcfg).read().splitlines():
cfg = cfg.split('#', 1)[0]
kv = ' '.join(shlex.split(cfg)).split('=', 1)
try:
kv = ' '.join(shlex.split(cfg)).split('=', 1)
except Exception:
# unparseable line, likely having something we can't handle
del self.cfgbydev[devname]
if len(kv) != 2:
continue
k, v = kv
@@ -191,7 +379,14 @@ class WickedManager(object):
class NetworkManager(object):
def __init__(self, devtypes):
bondtypes = {
'lacp': '802.3ad',
'loadbalance': 'balance-alb',
'roundrobin': 'balance-rr',
'activebackup': 'active-backup',
}
def __init__(self, devtypes, deploycfg):
self.deploycfg = deploycfg
self.connections = {}
self.uuidbyname = {}
self.uuidbydev = {}
@@ -236,12 +431,13 @@ class NetworkManager(object):
currteam = deats.get('connection.master', None)
if currteam == team:
return
for stg in ('ipv4.dhcp-hostname', 'ipv4.dns', 'ipv6.dns', 'ipv6.dhcp-hostname'):
for stg in ('ipv4.dhcp-hostname', 'ipv4.dns', 'ipv6.dns', 'ipv6.dhcp-hostname', 'ipv4.dns-search', 'ipv6.dns-search'):
if deats.get(stg, None):
bondcfg[stg] = deats[stg]
if member in self.uuidbyname:
subprocess.check_call(['nmcli', 'c', 'del', self.uuidbyname[member]])
subprocess.check_call(['nmcli', 'c', 'add', 'type', 'team-slave', 'master', team, 'con-name', member, 'connection.interface-name', member])
devtype = self.devtypes.get(member, 'bond-slave')
subprocess.check_call(['nmcli', 'c', 'add', 'type', devtype, 'master', team, 'con-name', member, 'connection.interface-name', member])
if bondcfg:
args = []
for parm in bondcfg:
@@ -249,8 +445,9 @@ class NetworkManager(object):
args.append(bondcfg[parm])
subprocess.check_call(['nmcli', 'c', 'm', team] + args)
def apply_configuration(self, cfg):
def apply_configuration(self, cfg, lastchance=False):
cmdargs = {}
cmdargs['connection.autoconnect'] = 'yes'
stgs = cfg['settings']
cmdargs['ipv6.method'] = stgs.get('ipv6_method', 'link-local')
if stgs.get('ipv6_address', None):
@@ -262,6 +459,22 @@ class NetworkManager(object):
cmdargs['ipv4.gateway'] = stgs['ipv4_gateway']
if stgs.get('ipv6_gateway', None):
cmdargs['ipv6.gateway'] = stgs['ipv6_gateway']
if stgs.get('mtu', None):
cmdargs['802-3-ethernet.mtu'] = stgs['mtu']
dnsips = self.deploycfg.get('nameservers', [])
if not dnsips:
dnsips = []
dns4 = []
dns6 = []
for dnsip in dnsips:
if '.' in dnsip:
dns4.append(dnsip)
elif ':' in dnsip:
dns6.append(dnsip)
if dns4:
cmdargs['ipv4.dns'] = ','.join(dns4)
if dns6:
cmdargs['ipv6.dns'] = ','.join(dns6)
if len(cfg['interfaces']) > 1: # team time.. should be..
if not cfg['settings'].get('team_mode', None):
sys.stderr.write("Warning, multiple interfaces ({0}) without a team_mode, skipping setup\n".format(','.join(cfg['interfaces'])))
@@ -273,31 +486,58 @@ class NetworkManager(object):
cargs = []
for arg in cmdargs:
cargs.append(arg)
cargs.append(cmdargs[arg])
subprocess.check_call(['nmcli', 'c', 'add', 'type', 'team', 'con-name', cname, 'connection.interface-name', cname, 'team.runner', stgs['team_mode']] + cargs)
cargs.append('{}'.format(cmdargs[arg]))
if stgs['team_mode'] in self.bondtypes:
stgs['team_mode'] = self.bondtypes[stgs['team_mode']]
subprocess.check_call(['nmcli', 'c', 'add', 'type', 'bond', 'con-name', cname, 'connection.interface-name', cname, 'bond.options', 'miimon=100,mode={}'.format(stgs['team_mode'])] + cargs)
for iface in cfg['interfaces']:
self.add_team_member(cname, iface)
subprocess.check_call(['nmcli', 'c', 'u', cname])
else:
cname = stgs.get('connection_name', None)
iname = list(cfg['interfaces'])[0]
if not cname:
cname = iname
ctype = self.devtypes.get(iname, None)
if not ctype:
if lastchance:
sys.stderr.write("Warning, no device found for interface_name ({0}), skipping setup\n".format(iname))
return 1
if stgs.get('vlan_id', None):
vlan = stgs['vlan_id']
if ctype == 'infiniband':
vlan = '0x{0}'.format(vlan) if not vlan.startswith('0x') else vlan
cmdargs['infiniband.parent'] = iname
cmdargs['infiniband.p-key'] = vlan
iname = '{0}.{1}'.format(iname, vlan[2:])
elif ctype == 'ethernet':
ctype = 'vlan'
cmdargs['vlan.parent'] = iname
cmdargs['vlan.id'] = vlan
iname = '{0}.{1}'.format(iname, vlan)
else:
sys.stderr.write("Warning, unknown interface_name ({0}) device type ({1}) for VLAN/PKEY, skipping setup\n".format(iname, ctype))
return
cname = iname if not cname else cname
u = self.uuidbyname.get(cname, None)
cargs = []
for arg in cmdargs:
cargs.append(arg)
cargs.append(cmdargs[arg])
cargs.append('{}'.format(cmdargs[arg]))
if u:
cmdargs['connection.interface-name'] = iname
subprocess.check_call(['nmcli', 'c', 'm', u] + cargs)
subprocess.check_call(['nmcli', 'c', 'm', u, 'connection.interface-name', iname] + cargs)
subprocess.check_call(['nmcli', 'c', 'u', u])
else:
subprocess.check_call(['nmcli', 'c', 'add', 'type', self.devtypes[iname], 'con-name', cname, 'connection.interface-name', iname] + cargs)
subprocess.check_call(['nmcli', 'c', 'add', 'type', ctype, 'con-name', cname, 'connection.interface-name', iname] + cargs)
self.read_connections()
u = self.uuidbyname.get(cname, None)
if u:
subprocess.check_call(['nmcli', 'c', 'u', u])
if __name__ == '__main__':
checktarg = None
if '-c' in sys.argv:
checktarg = sys.argv[sys.argv.index('-c') + 1]
havefirewall = subprocess.call(['systemctl', 'status', 'firewalld'])
havefirewall = havefirewall == 0
if havefirewall:
@@ -309,22 +549,52 @@ if __name__ == '__main__':
myaddrs = apiclient.get_my_addresses()
srvs, _ = apiclient.scan_confluents()
doneidxs = set([])
dc = None
if not srvs: # the multicast scan failed, fallback to deploycfg cfg file
with open('/etc/confluent/confluent.deploycfg', 'r') as dci:
for cfgline in dci.read().split('\n'):
if cfgline.startswith('deploy_server:'):
srvs = [cfgline.split()[1]]
break
for srv in srvs:
s = socket.create_connection((srv, 443))
try:
s = socket.create_connection((srv, 443))
except socket.error:
continue
myname = s.getsockname()
s.close()
curridx = None
if len(myname) == 4:
curridx = myname[-1]
else:
myname = myname[0]
myname = socket.inet_pton(socket.AF_INET, myname)
for addr in myaddrs:
if myname == addr[1].tobytes():
if myname == addr[1]:
curridx = addr[-1]
if curridx in doneidxs:
if curridx is not None and curridx in doneidxs:
continue
status, nc = apiclient.HTTPSClient(usejson=True, host=srv).grab_url_with_status('/confluent-api/self/netcfg')
for tries in (1, 2, 3):
try:
status, nc = apiclient.HTTPSClient(usejson=True, host=srv).grab_url_with_status('/confluent-api/self/netcfg')
break
except Exception:
if tries == 3:
raise
time.sleep(1)
continue
nc = json.loads(nc)
if not dc:
for tries in (1, 2, 3):
try:
status, dc = apiclient.HTTPSClient(usejson=True, host=srv).grab_url_with_status('/confluent-api/self/deploycfg2')
break
except Exception:
if tries == 3:
raise
time.sleep(1)
continue
dc = json.loads(dc)
iname = get_interface_name(idxmap[curridx], nc.get('default', {}))
if iname:
for iname in iname.split(','):
@@ -342,14 +612,61 @@ if __name__ == '__main__':
else:
netname_to_interfaces[uname] = {'interfaces': set([iname]), 'settings': nc['extranets'][netname]}
doneidxs.add(curridx)
if 'default' in netname_to_interfaces:
for netn in netname_to_interfaces:
if netn == 'default':
continue
netname_to_interfaces['default']['interfaces'] -= netname_to_interfaces[netn]['interfaces']
if not netname_to_interfaces['default']['interfaces']:
del netname_to_interfaces['default']
# Make sure VLAN/PKEY connections are created last
netname_to_interfaces = dict(sorted(netname_to_interfaces.items(), key=lambda item: 'vlan_id' in item[1]['settings']))
rm_tmp_llas(tmpllas)
if os.path.exists('/usr/bin/nmcli'):
nm = NetworkManager(devtypes)
if os.path.exists('/usr/sbin/netplan'):
nm = NetplanManager(dc)
elif os.path.exists('/usr/bin/nmcli'):
nm = NetworkManager(devtypes, dc)
elif os.path.exists('/usr/sbin/wicked'):
nm = WickedManager()
retrynics = []
for netn in netname_to_interfaces:
nm.apply_configuration(netname_to_interfaces[netn])
redo = nm.apply_configuration(netname_to_interfaces[netn])
if redo == 1:
retrynics.append(netn)
if retrynics:
idxmap, devtypes = map_idx_to_name()
if os.path.exists('/usr/sbin/netplan'):
nm = NetplanManager(dc)
if os.path.exists('/usr/bin/nmcli'):
nm = NetworkManager(devtypes, dc)
elif os.path.exists('/usr/sbin/wicked'):
nm = WickedManager()
for netn in retrynics:
nm.apply_configuration(netname_to_interfaces[netn], lastchance=True)
if havefirewall:
subprocess.check_call(['systemctl', 'start', 'firewalld'])
await_tentative()
maxwait = 10
while maxwait:
try:
tclient = apiclient.HTTPSClient(checkonly=True)
tclient.check_connections()
break
except Exception:
maxwait -= 1
time.sleep(1)
maxwait = 10
if checktarg:
while maxwait:
try:
addrinf = socket.getaddrinfo(checktarg, 443)[0]
psock = socket.socket(addrinf[0], socket.SOCK_STREAM)
psock.settimeout(10)
psock.connect(addrinf[4])
psock.close()
break
except Exception:
maxwait -= 1
time.sleep(1)
@@ -0,0 +1,63 @@
[ -f /lib/confluent/functions ] && . /lib/confluent/functions
[ -f /etc/confluent/functions ] && . /etc/confluent/functions
[ -f /opt/confluent/bin/apiclient ] && confapiclient=/opt/confluent/bin/apiclient
[ -f /etc/confluent/apiclient ] && confapiclient=/etc/confluent/apiclient
for pubkey in /etc/ssh/ssh_host*key.pub; do
if [ "$pubkey" = /etc/ssh/ssh_host_key.pub ]; then
continue
fi
certfile=${pubkey/.pub/-cert.pub}
echo -n > $certfile
confluentpython $confapiclient /confluent-api/self/sshcert $pubkey -o $certfile
done
if [ -d /etc/ssh/sshd_config.d/ -a ! -e /etc/ssh/sshd_config.d/90-confluent.conf ]; then
for cert in /etc/ssh/ssh*-cert.pub; do
echo HostCertificate $cert >> /etc/ssh/sshd_config.d/90-confluent.conf
done
echo HostbasedAuthentication yes >> /etc/ssh/sshd_config.d/90-confluent.conf
echo HostbasedUsesNameFromPacketOnly yes >> /etc/ssh/sshd_config.d/90-confluent.conf
echo IgnoreRhosts no >> /etc/ssh/sshd_config.d/90-confluent.conf
elif [ ! -d /etc/ssh/sshd_config.d/ ] && ! grep HostCertificate /etc/ssh/sshd_config > /dev/null; then
for cert in /etc/ssh/ssh*-cert.pub; do
echo HostCertificate $cert >> /etc/ssh/sshd_config
done
echo HostbasedAuthentication yes >> /etc/ssh/sshd_config
echo HostbasedUsesNameFromPacketOnly yes >> /etc/ssh/sshd_config
echo IgnoreRhosts no >> /etc/ssh/sshd_config
fi
TMPDIR=$(mktemp -d)
cd $TMPDIR
confluentpython $confapiclient /confluent-public/site/initramfs.tgz -o initramfs.tgz
tar xf initramfs.tgz
for ca in ssh/*.ca; do
LINE=$(cat $ca)
if [ -z "$LINE" ]; then continue; fi
if [ -f /etc/ssh/ssh_known_hosts ]; then
cp -af /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts.new
grep -v "$LINE" /etc/ssh/ssh_known_hosts > /etc/ssh/ssh_known_hosts.new
fi
echo '@cert-authority *' $LINE >> /etc/ssh/ssh_known_hosts.new
mv /etc/ssh/ssh_known_hosts.new /etc/ssh/ssh_known_hosts
done
mkdir -p /root/.ssh/
chmod 700 /root/.ssh/
touch /root/.ssh/authorized_keys
for pubkey in ssh/*.*pubkey; do
LINE=$(cat $pubkey)
if [ -z "$LINE" ]; then continue; fi
cp -af /root/.ssh/authorized_keys /root/.ssh/authorized_keys.new
grep -v "$LINE" /root/.ssh/authorized_keys > /root/.ssh/authorized_keys.new
echo "$LINE" >> /root/.ssh/authorized_keys.new
mv /root/.ssh/authorized_keys.new /root/.ssh/authorized_keys
done
confluentpython $confapiclient /confluent-api/self/nodelist | sed -e 's/^- //' > /etc/ssh/shosts.equiv
cat /etc/ssh/shosts.equiv > /root/.shosts
cd -
rm -rf $TMPDIR
# ssh may be sshd or ssh, depending
if systemctl list-unit-files | grep -q '^sshd\.service'; then
systemctl try-restart sshd
elif systemctl list-unit-files | grep -q '^ssh\.service'; then
systemctl try-restart ssh
fi
@@ -0,0 +1,103 @@
Name: confluent_osdeploy-aarch64
Version: #VERSION#
Release: 1
Summary: OS Deployment support for confluent
License: Apache2
URL: https://hpc.lenovo.com/
Source0: confluent_osdeploy.tar.xz
Source1: confluent_el9bin.tar.xz
Source2: confluent_el8bin.tar.xz
BuildArch: noarch
Requires: confluent_ipxe mtools tar
BuildRoot: /tmp
%description
This contains support utilities for enabling deployment of aarch64 architecture systems
%define debug_package %{nil}
%prep
%setup -n confluent_osdeploy -a 2 -a 1
%build
mkdir -p opt/confluent/bin
mkdir -p stateless-bin
cp -a el8bin/* .
ln -s el8 el9
cp -a el8 el10
cp -a debian debian13
mkdir -p debian13/initramfs/usr
mv debian13/initramfs/lib debian13/initramfs/usr/
mv el10/initramfs/usr el10/initramfs/var
for os in rhvh4 el7 genesis el8 suse15 debian debian13 ubuntu20.04 ubuntu22.04 ubuntu24.04 ubuntu26.04 coreos el9 el10; do
mkdir ${os}out
cd ${os}out
if [ -d ../${os}bin ]; then
cp -a ../${os}bin/opt .
elif [ $os = el10 ]; then
cp -a ../el9bin/opt .
else
cp -a ../opt .
fi
cp -a ../${os}/initramfs/* .
cp -a ../common/initramfs/* .
find . | cpio -H newc -o > ../addons.cpio
mv ../addons.cpio .
cd ..
done
for os in el7 el8 suse15 el9 el10 ubuntu20.04 ubuntu22.04 ubuntu24.04 ubuntu26.04; do
mkdir ${os}disklessout
cd ${os}disklessout
if [ -d ../${os}bin ]; then
cp -a ../${os}bin/opt .
elif [ $os = el10 ]; then
cp -a ../el9bin/opt .
else
cp -a ../opt .
fi
cp -a ../${os}-diskless/initramfs/* .
cp -a ../common/initramfs/* .
if [ -d ../${os}bin ]; then
cp -a ../${os}bin/stateless-bin/* opt/confluent/bin
else
cp -a ../stateless-bin/* opt/confluent/bin
fi
find . | cpio -H newc -o > ../addons.cpio
mv ../addons.cpio .
cd ..
done
mkdir esxi7out
cd esxi7out
cp -a ../opt .
cp -a ../esxi7/initramfs/* .
cp -a ../common/initramfs/* .
chmod +x bin/* opt/confluent/bin/*
tar zcvf ../addons.tgz *
mv ../addons.tgz .
cd ..
cp -a esxi7out esxi6out
cp -a esxi7 esxi6
cp -a esxi7out esxi8out
cp -a esxi7 esxi8
%install
mkdir -p %{buildroot}/opt/confluent/share/licenses/confluent_osdeploy/
#cp LICENSE %{buildroot}/opt/confluent/share/licenses/confluent_osdeploy/
mkdir -p %{buildroot}/opt/confluent/lib/osdeploy/common
cp common/initramfs/opt/confluent/bin/apiclient %{buildroot}/opt/confluent/lib/osdeploy/common
for os in rhvh4 el7 el8 el9 el10 debian debian13 genesis suse15 ubuntu20.04 ubuntu22.04 ubuntu24.04 ubuntu26.04 esxi6 esxi7 esxi8 coreos; do
mkdir -p %{buildroot}/opt/confluent/lib/osdeploy/$os/initramfs/aarch64/
cp ${os}out/addons.* %{buildroot}/opt/confluent/lib/osdeploy/$os/initramfs/aarch64/
if [ -d ${os}disklessout ]; then
mkdir -p %{buildroot}/opt/confluent/lib/osdeploy/${os}-diskless/initramfs/aarch64/
cp ${os}disklessout/addons.* %{buildroot}/opt/confluent/lib/osdeploy/${os}-diskless/initramfs/aarch64/
fi
done
find %{buildroot}/opt/confluent/lib/osdeploy/ -name .gitignore -exec rm -f {} +
%files
/opt/confluent/lib/osdeploy
#%license /opt/confluent/share/licenses/confluent_osdeploy/LICENSE
+27 -16
View File
@@ -7,6 +7,7 @@ License: Apache2
URL: https://hpc.lenovo.com/
Source0: confluent_osdeploy.tar.xz
Source1: confluent_el9bin.tar.xz
Source2: confluent_el8bin.tar.xz
BuildArch: noarch
Requires: confluent_ipxe mtools tar
BuildRoot: /tmp
@@ -18,25 +19,29 @@ This contains support utilities for enabling deployment of x86_64 architecture s
%define debug_package %{nil}
%prep
%setup -n confluent_osdeploy -a 1
%setup -n confluent_osdeploy -a 2 -a 1
%build
mkdir -p opt/confluent/bin
mkdir -p stateless-bin
cd utils
make all
cp confluent_imginfo copernicus clortho autocons ../opt/confluent/bin
cp start_root urlmount ../stateless-bin/
cd ..
#cd utils
#make all
#cp confluent_imginfo copernicus clortho autocons ../opt/confluent/bin
#cp start_root urlmount ../stateless-bin/
#cd ..
ln -s el8 el9
ln -s el8-diskless el9-diskless
for os in rhvh4 el7 genesis el8 suse15 ubuntu20.04 ubuntu22.04 coreos el9; do
cp -a el8 el10
cp -a debian debian13
mkdir -p debian13/initramfs/usr
mv debian13/initramfs/lib debian13/initramfs/usr/
mv el10/initramfs/usr el10/initramfs/var
for os in rhvh4 el7 genesis el8 suse15 debian debian13 ubuntu18.04 ubuntu20.04 ubuntu22.04 ubuntu24.04 ubuntu26.04 coreos el9 el10; do
mkdir ${os}out
cd ${os}out
if [ -d ../${os}bin ]; then
cp -a ../${os}bin/opt .
elif [ $os = el10 ]; then
cp -a ../el9bin/opt .
else
cp -a ../opt .
cp -a ../el8bin/opt .
fi
cp -a ../${os}/initramfs/* .
cp -a ../common/initramfs/* .
@@ -44,20 +49,22 @@ for os in rhvh4 el7 genesis el8 suse15 ubuntu20.04 ubuntu22.04 coreos el9; do
mv ../addons.cpio .
cd ..
done
for os in el7 el8 suse15 el9 ubuntu20.04; do
for os in el7 el8 suse15 el9 el10 ubuntu20.04 ubuntu22.04 ubuntu24.04 ubuntu26.04; do
mkdir ${os}disklessout
cd ${os}disklessout
if [ -d ../${os}bin ]; then
cp -a ../${os}bin/opt .
elif [ $os = el10 ]; then
cp -a ../el9bin/opt .
else
cp -a ../opt .
cp -a ../el8bin/opt .
fi
cp -a ../${os}-diskless/initramfs/* .
cp -a ../common/initramfs/* .
if [ -d ../${os}bin ]; then
cp -a ../${os}bin/stateless-bin/* opt/confluent/bin
else
cp -a ../stateless-bin/* opt/confluent/bin
cp -a ../el8bin/stateless-bin/* opt/confluent/bin
fi
find . | cpio -H newc -o > ../addons.cpio
mv ../addons.cpio .
@@ -65,7 +72,7 @@ for os in el7 el8 suse15 el9 ubuntu20.04; do
done
mkdir esxi7out
cd esxi7out
cp -a ../opt .
cp -a ../el8bin/opt .
cp -a ../esxi7/initramfs/* .
cp -a ../common/initramfs/* .
chmod +x bin/* opt/confluent/bin/*
@@ -74,11 +81,15 @@ mv ../addons.tgz .
cd ..
cp -a esxi7out esxi6out
cp -a esxi7 esxi6
cp -a esxi7out esxi8out
cp -a esxi7out esxi9out
cp -a esxi7 esxi8
cp -a esxi7 esxi9
%install
mkdir -p %{buildroot}/opt/confluent/share/licenses/confluent_osdeploy/
cp LICENSE %{buildroot}/opt/confluent/share/licenses/confluent_osdeploy/
for os in rhvh4 el7 el8 el9 genesis suse15 ubuntu20.04 ubuntu22.04 esxi6 esxi7 coreos; do
for os in rhvh4 el7 el8 el9 el10 genesis suse15 ubuntu20.04 debian debian13 ubuntu18.04 ubuntu22.04 ubuntu24.04 ubuntu26.04 esxi6 esxi7 esxi8 esxi9 coreos; do
mkdir -p %{buildroot}/opt/confluent/lib/osdeploy/$os/initramfs
mkdir -p %{buildroot}/opt/confluent/lib/osdeploy/$os/profiles
cp ${os}out/addons.* %{buildroot}/opt/confluent/lib/osdeploy/$os/initramfs
@@ -12,7 +12,7 @@ if [ -e /dev/disk/by-label/CNFLNT_IDNT ]; then
cd $tmnt
deploysrvs=$(sed -n '/^deploy_servers:/, /^[^-]/p' cnflnt.yml |grep ^-|sed -e 's/^- //'|grep -v :)
nodename=$(grep ^nodename: cnflnt.yml|awk '{print $2}')
sed -n '/^net_cfgs:/, /^[^- ]/p' cnflnt.yml |grep '^[ -]'|sed -n '/^-/, /^-/p'|head -n -1 | sed -e 's/^[- ]*//'> $tcfg
sed -n '/^net_cfgs:/, /^[^- ]/{/^[^- ]/!p}' cnflnt.yml |sed -n '/^-/, /^-/{/^-/!p}'| sed -e 's/^[- ]*//'> $tcfg
autoconfigmethod=$(grep ^ipv4_method: $tcfg)
autoconfigmethod=${autoconfigmethod#ipv4_method: }
if [ "$autoconfigmethod" = "dhcp" ]; then
@@ -20,6 +20,7 @@ if [ -e /dev/disk/by-label/CNFLNT_IDNT ]; then
else
v4addr=$(grep ^ipv4_address: $tcfg)
v4addr=${v4addr#ipv4_address: }
v4addr=${v4addr%/*}
v4gw=$(grep ^ipv4_gateway: $tcfg)
v4gw=${v4gw#ipv4_gateway: }
if [ "$v4gw" = "null" ]; then
@@ -66,6 +67,7 @@ while ! grep ^NODE /etc/confluent/confluent.info; do
if ! grep ^NODE /etc/confluent/confluent.info; then
echo 'Current net config:' > /dev/console
ip -br a > /dev/console
exit 1
fi
done
echo "Found confluent deployment services on local network" > /dev/console
@@ -0,0 +1,217 @@
reverse_uuid() {
echo $1 | head -c 8 | tail -c 2
echo $1 | head -c 6 | tail -c 2
echo $1 | head -c 4 | tail -c 2
echo $1 | head -c 2 | tail -c 2
echo $1 | head -c 13 | tail -c 2
echo $1 | head -c 11 | tail -c 2
echo $1 | head -c 18 | tail -c 2
echo $1 | head -c 16 | tail -c 2
echo $1 | tail -c 18 | sed -e s/-//
}
setdebopt() {
debconf-set $1 $2
echo d-i $1 $3 $2 >> /preseed.cfg
}
mkdir -p /etc/confluent
for i in /sys/class/net/*; do
ip link set $(basename $i) up
done
TRIES=5
while [ ! -e /dev/disk ] && [ $TRIES -gt 0 ]; do
sleep 2
TRIES=$((TRIES - 1))
done
for i in /sys/class/net/*; do
ip link set $(basename $i) down
udevadm info $i | grep ID_NET_DRIVER=cdc_ether > /dev/null && continue
ip link set $(basename $i) up
done
cp -a /tls/* /etc/ssl/certs/
mkdir -p /etc/confluent
if [ -e /dev/disk/by-label/CNFLNT_IDNT ]; then
tmnt=$(mktemp -d)
tcfg=$(mktemp)
mount /dev/disk/by-label/CNFLNT_IDNT $tmnt
cd $tmnt
deploysrvs=$(sed -n '/^deploy_servers:/,/^[^-]/p' cnflnt.yml |grep ^-|sed -e 's/^- //'|grep -v :)
nodename=$(grep ^nodename: cnflnt.yml|cut -f 2 -d ' ')
echo NODENAME: $nodename > /etc/confluent/confluent.info
sed -n '/^net_cfgs:/,/^[^- ]/{/^[^- ]/!p}' cnflnt.yml |sed -n '/^-/,/^-/{/^-/!p}'| sed -e 's/^[- ]*//'> $tcfg
autoconfigmethod=$(grep ^ipv4_method: $tcfg)
autoconfigmethod=${autoconfigmethod#ipv4_method: }
if [ "$autoconfigmethod" = "static" ]; then
setdebopt netcfg/disable_dhcp true boolean
v4addr=$(grep ^ipv4_address: $tcfg|cut -d: -f 2|sed -e 's/ //')
v4gw=$(grep ^ipv4_gateway: $tcfg|cut -d: -f 2| sed -e 's/ //')
if [ "$v4gw" = "null" ]; then
v4gw=""
fi
v4nm=$(grep ^ipv4_netmask: $tcfg|cut -d: -f 2|sed -e 's/ //')
setdebopt netcfg/get_netmask $v4nm string
setdebopt netcfg/get_ipaddress ${v4addr%/*} string
setdebopt netcfg/confirm_static true boolean
if [ ! -z "$v4gw" ]; then
setdebopt netcfg/get_gateway $v4gw string
fi
NIC=""
while [ -z "$NIC" ]; do
for NICGUESS in $(ip link|grep LOWER_UP|grep -v LOOPBACK|cut -d ' ' -f 2 | sed -e 's/:$//'); do
ip addr add dev $NICGUESS $v4addr
if [ ! -z "$v4gw" ]; then
ip route add default via $v4gw
fi
for dsrv in $deploysrvs; do
if wget https://$dsrv/confluent-public/ --tries=1 --timeout=1 -O /dev/null > /dev/null 2>&1; then
deploysrvs=$dsrv
NIC=$NICGUESS
setdebopt netcfg/choose_interface $NIC select
break
fi
done
if [ -z "$NIC" ]; then
ip -4 a flush dev $NICGUESS
else
break
fi
done
done
#TODO: nameservers
elif [ "$v4cfgmeth" = "dhcp" ]; then
setdebopt netcfg/disable_dhcp false boolean
setdebopt netcfg/confirm_static false boolean
for NICGUESS in $(ip link|grep LOWER_UP|grep -v LOOPBACK|cut -d ' ' -f 2 | sed -e 's/:$//'); do
udhcpc $NICGUESS
done
for dsrv in $deploysrvs; do
if wget https://$dsrv/confluent-public/ --tries=1 --timeout=1 -O /dev/null > /dev/null 2>&1; then
deploysrvs=$dsrv
fi
done
fi
mgr=$deploysrvs
ln -s /opt/confluent/bin/clortho /opt/confluent/bin/genpasshmac
hmackeyfile=/tmp/cnflnthmackeytmp
passfile=/tmp/cnflnttmppassfile
passcrypt=/tmp/cnflntcryptfile
hmacfile=/tmp/cnflnthmacfile
echo -n $(grep ^apitoken: cnflnt.yml|cut -d ' ' -f 2) > $hmackeyfile
/opt/confluent/bin/genpasshmac $passfile $passcrypt $hmacfile $hmackeyfile
wget --header="CONFLUENT_NODENAME: $nodename" --header="CONFLUENT_CRYPTHMAC: $(cat $hmacfile)" --post-file=$passcrypt https://$mgr/confluent-api/self/registerapikey -O - --quiet
cp $passfile /etc/confluent/confluent.apikey
nic=$NIC
else
dhuuid=$(reverse_uuid $(cat /sys/devices/virtual/dmi/id/product_uuid))
dhcpid=$(mktemp)
mkdir -p /etc/confluent
cp /tls/* /etc/ssl/certs/
cat /tls/*.pem >> /etc/confluent/ca.pem
for nic in $(ip link | grep mtu|grep -v LOOPBACK|cut -d: -f 2|sed -e 's/ //'); do
ip link set $nic up
done
nic=
while [ -z "$nic" ]; do
for nic in $(ip link | grep mtu|grep -v LOOPBACK|grep LOWER_UP|cut -d: -f 2|sed -e 's/ //'); do
if udhcpc -i $nic -p $dhcpid -t 2 -T 2 -n -x 93:0007 -x 97:00$dhuuid -q; then
/opt/confluent/bin/copernicus > /etc/confluent/confluent.info
if grep ^MANAGER:.*\\. /etc/confluent/confluent.info ; then
break
fi
fi
ip -4 address flush dev $nic
nic=""
done
if [ -z "$nic" ]; then
echo "No network interface could be detected, retrying...."
sleep 2
fi
done
mgr=$(grep ^MANAGER:.*\\. /etc/confluent/confluent.info|head -n 1|cut -d: -f 2|sed -e 's/ //')
nodename=$(grep ^NODENAME: /etc/confluent/confluent.info|head -n 1|cut -d: -f 2|sed -e 's/ //')
/opt/confluent/bin/clortho $nodename $mgr > /etc/confluent/confluent.apikey
fi
apikey=$(cat /etc/confluent/confluent.apikey)
cd /etc/confluent
wget --header="CONFLUENT_NODENAME: $nodename" --header="CONFLUENT_APIKEY: $apikey" https://$mgr/confluent-api/self/deploycfg
cd -
predir=$(mktemp -d)
cd $predir
cp /etc/confluent/deploycfg /etc/confluent/confluent.deploycfg
profile=$(grep ^profile: /etc/confluent/deploycfg|cut -d ' ' -f 2)
namesrvs=$(sed -n '/^nameservers:/,/^[^-]/p' /etc/confluent/deploycfg|grep ^- | cut -d ' ' -f 2|sed -e 's/ //')
for namesrv in "$namesrvs"; do
setdebopt netcfg/get_nameservers $namesrv string
done
rootpass=$(grep ^rootpassword: /etc/confluent/deploycfg|cut -d ' ' -f 2|sed -e 's/ //')
if [ "$rootpass" = null ] || [ -z "$rootpass" ]; then
setdebopt passwd/root-login false boolean
else
setdebopt passwd/root-login true boolean
setdebopt passwd/root-password-crypted $rootpass string
fi
setdebopt time/zone $(grep ^timezone: /etc/confluent/deploycfg|cut -d ' ' -f 2|sed -e 's/ //') string
ntpsrvs=$(sed -n '/^ntpservers:/,/^[^-]/p' /etc/confluent/deploycfg|grep ^- | cut -d ' ' -f 2|sed -e 's/ //')
for ntpsrv in "$ntpsrvs"; do
setdebopt clock-setup/ntp true boolean
setdebopt clock-setup/ntp-server $ntpsrv string
done
setdebopt debian-installer/locale $(grep ^locale: /etc/confluent/deploycfg|cut -d ' ' -f 2) select
domainname=$(grep ^dnsdomain: /etc/confluent/deploycfg|cut -d ' ' -f 2)
if [ ! -z "$domainname" ] && [ "$domainname" != "null" ]; then
setdebopt netcfg/get_domain $domainname string
fi
wget https://$mgr/confluent-public/os/$profile/scripts/pre.sh
chmod u+x pre.sh
wget https://$mgr/confluent-public/os/$profile/scripts/prechroot.sh
chmod u+x prechroot.sh
wget https://$mgr/confluent-public/os/$profile/scripts/post.sh
chmod u+x post.sh
wget https://$mgr/confluent-public/os/$profile/preseed.cfg
cat preseed.cfg >> /preseed.cfg
echo $mgr > /etc/confluent/deployer
setdebopt auto-install/enable true boolean
setdebopt partman/early_command $predir/pre.sh string
setdebopt preseed/late_command $predir/prechroot.sh string
mv $predir/post.sh /tmp/
cd -
ip -4 a flush dev $nic
setdebopt netcfg/choose_interface $nic select
setdebopt netcfg/get_hostname $nodename string
setdebopt netcfg/hostname $nodename string
setdebopt mirror/protocol https string
setdebopt mirror/country manual string
setdebopt mirror/https/hostname deb.debian.org string
setdebopt mirror/https/directory /debian/ string
setdebopt mirror/protocol https string
setdebopt mirror/https/proxy "" string
#setdebopt apt-setup/security_host $mgr string
if [ ! -e /dev/disk/by-label/CNFLNT_IDNT ]; then
v4cfgmeth=$(grep ipv4_method: /etc/confluent/deploycfg |cut -d: -f 2|sed -e 's/ //')
if [ "$v4cfgmeth" = "static" ]; then
setdebopt netcfg/disable_dhcp true boolean
v4addr=$(grep ^ipv4_address: /etc/confluent/deploycfg|cut -d: -f 2|sed -e 's/ //')
v4gw=$(grep ^ipv4_gateway: /etc/confluent/deploycfg|cut -d: -f 2| sed -e 's/ //')
if [ "$v4gw" = "null" ]; then
v4gw=""
fi
v4nm=$(grep ^ipv4_netmask: /etc/confluent/deploycfg|cut -d: -f 2|sed -e 's/ //')
setdebopt netcfg/get_netmask $v4nm string
setdebopt netcfg/get_ipaddress $v4addr string
setdebopt netcfg/confirm_static true boolean
if [ ! -z "$v4gw" ]; then
setdebopt netcfg/get_gateway $v4gw string
fi
namesrvs=$(sed -n '/^nameservers:/,/^[^-]/p' /etc/confluent/deploycfg|grep ^- | cut -d ' ' -f 2|sed -e 's/ //')
for namesrv in "$namesrvs"; do
setdebopt netcfg/get_nameservers $namesrv string
done
elif [ "$vpcfgmeth" = "dhcp" ]; then
setdebopt netcfg/disable_dhcp false boolean
setdebopt netcfg/confirm_static false boolean
fi
fi
@@ -0,0 +1,8 @@
#!/bin/sh
sed -i 's/label: debian/label: Debian/' $2/profile.yaml && \
ln -s $1/linux $2/boot/kernel && \
ln -s $1/initrd.gz $2/boot/initramfs/distribution && \
mkdir -p $2/boot/efi/boot && \
rm $2/distribution && \
mcopy -i $1/boot/grub/efi.img ::/efi/boot/* $2/boot/efi/boot
@@ -0,0 +1,27 @@
d-i anna/choose_modules string openssh-server-udeb
d-i partman-auto/method string regular
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-auto/expert_recipe_file string /tmp/partitionfile
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i passwd/make-user boolean false
d-i clock-setup/utc boolean true
d-i apt-setup/multiverse boolean false
d-i apt-setup/universe boolean false
d-i apt-setup/backports boolean false
d-i apt-setup/updates boolean false
d-i grub-installer/only_debian boolean true
tasksel tasksel/first multiselect standard
d-i pkgsel/include string openssh-server curl
d-i pkgsel/update-policy select none
d-i pkgsel/updatedb boolean false
d-i finish-install/reboot_in_progress note
popularity-contest popularity-contest/participate boolean false
d-i partman-auto/method string lvm
d-i partman-auto/choose_recipe select atomic
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-auto-lvm/guided_size string max
@@ -0,0 +1,3 @@
label: %%DISTRO%% %%VERSION%% %%ARCH%% (Default Profile)
kernelargs: quiet osprofile=%%PROFILE%%
#installedargs: example # These arguments would be added to the installed system
@@ -0,0 +1,570 @@
#!/usr/bin/python
import glob
import json
import os
import socket
import sys
import time
import shlex
import subprocess
try:
import yaml
except ImportError:
pass
try:
from importlib.machinery import SourceFileLoader
def load_source(mod, path):
return SourceFileLoader(mod, path).load_module()
except ImportError:
from imp import load_source
try:
apiclient = load_source('apiclient', '/opt/confluent/bin/apiclient')
except IOError:
apiclient = load_source('apiclient', '/etc/confluent/apiclient')
def add_lla(iface, mac):
pieces = mac.split(':')
initbyte = int(pieces[0], 16) ^ 2
lla = 'fe80::{0:x}{1}:{2}ff:fe{3}:{4}{5}/64'.format(initbyte, pieces[1], pieces[2], pieces[3], pieces[4], pieces[5])
try:
with open('/proc/sys/net/ipv6/conf/{0}/disable_ipv6'.format(iface), 'w') as setin:
setin.write('0')
subprocess.check_call(['ip', 'addr', 'add', 'dev', iface, lla, 'scope', 'link'])
except Exception:
return None
return lla
#cli = apiclient.HTTPSClient(json=True)
#c = cli.grab_url_with_status('/confluent-api/self/netcfg')
def add_missing_llas():
#NetworkManager goes out of its way to suppress ipv6 lla, so will just add some
added = {}
linkinfo = subprocess.check_output(['ip', '-br', 'l']).decode('utf8')
ifaces = {}
for line in linkinfo.split('\n'):
line = line.strip().split()
if not line or 'LOOPBACK' in line[-1] or 'NO-CARRIER' in line[-1]:
continue
if 'UP' not in line[-1]:
subprocess.call(['ip', 'link', 'set', line[0], 'up'])
ifaces[line[0]] = line[2]
ips = {}
ipinfo = subprocess.check_output(['ip', '-br', '-6', 'a']).decode('utf8')
for line in ipinfo.split('\n'):
line = line.strip().split(None, 2)
if not line:
continue
ips[line[0]] = line[2]
for iface in ifaces:
for addr in ips.get(iface, '').split():
if addr.startswith('fe80::'):
break
else:
newlla = add_lla(iface, ifaces[iface])
if newlla:
added[iface] = newlla
return added
def rm_tmp_llas(tmpllas):
for iface in tmpllas:
subprocess.check_call(['ip', 'addr', 'del', 'dev', iface, tmpllas[iface]])
def await_tentative():
maxwait = 10
while b'tentative' in subprocess.check_output(['ip', 'a']):
if maxwait == 0:
break
maxwait -= 1
time.sleep(1)
def map_idx_to_name():
map = {}
devtype = {}
prevdev = None
for line in subprocess.check_output(['ip', 'l']).decode('utf8').splitlines():
if line.startswith(' ') and 'link/' in line:
typ = line.split()[0].split('/')[1]
devtype[prevdev] = typ if typ != 'ether' else 'ethernet'
if line.startswith(' '):
continue
idx, iface, rst = line.split(':', 2)
prevdev = iface.strip()
rst = rst.split()
try:
midx = rst.index('master')
continue
except ValueError:
pass
idx = int(idx)
iface = iface.strip()
map[idx] = iface
return map, devtype
def get_interface_name(iname, settings):
explicitname = settings.get('interface_names', None)
if explicitname:
return explicitname
if settings.get('current_nic', False):
return iname
return None
class NetplanManager(object):
def __init__(self, deploycfg):
self.cfgbydev = {}
self.read_connections()
self.deploycfg = deploycfg
def read_connections(self):
for plan in glob.glob('/etc/netplan/*.y*ml'):
with open(plan) as planfile:
planinfo = yaml.safe_load(planfile)
if not planinfo:
continue
nicinfo = planinfo.get('network', {}).get('ethernets', {})
for devname in nicinfo:
if devname == 'lo':
continue
if 'gateway4' in nicinfo[devname]:
# normalize deprecated syntax on read in
gw4 = nicinfo[devname]['gateway4']
del nicinfo[devname]['gateway4']
routeinfo = nicinfo[devname].get('routes', [])
for ri in routeinfo:
if ri.get('via', None) == gw4 and ri.get('to', None) in ('default', '0.0.0.0/0', '0/0'):
break
else:
routeinfo.append({
'to': 'default',
'via': gw4
})
nicinfo[devname]['routes'] = routeinfo
self.cfgbydev[devname] = nicinfo[devname]
def apply_configuration(self, cfg):
devnames = cfg['interfaces']
if len(devnames) != 1:
raise Exception('Multi-nic team/bonds not yet supported')
stgs = cfg['settings']
needcfgapply = False
for devname in devnames:
needcfgwrite = False
# ipv6_method missing at uconn...
if stgs.get('ipv6_method', None) == 'static':
curraddr = stgs['ipv6_address']
currips = self.getcfgarrpath([devname, 'addresses'])
if curraddr not in currips:
needcfgwrite = True
currips.append(curraddr)
if stgs.get('ipv4_method', None) == 'static':
curraddr = stgs['ipv4_address']
currips = self.getcfgarrpath([devname, 'addresses'])
if curraddr not in currips:
needcfgwrite = True
currips.append(curraddr)
if stgs.get('mtu', None):
devdict = self.getcfgarrpath([devname])
devdict['mtu'] = int(stgs['mtu'])
gws = []
gws.append(stgs.get('ipv4_gateway', None))
gws.append(stgs.get('ipv6_gateway', None))
for gwaddr in gws:
if gwaddr:
cfgroutes = self.getcfgarrpath([devname, 'routes'])
for rinfo in cfgroutes:
if rinfo.get('via', None) == gwaddr:
break
else:
needcfgwrite = True
cfgroutes.append({'via': gwaddr, 'to': 'default'})
dnsips = self.deploycfg.get('nameservers', [])
dnsdomain = self.deploycfg.get('dnsdomain', '')
if dnsips:
currdnsips = self.getcfgarrpath([devname, 'nameservers', 'addresses'])
for dnsip in dnsips:
if dnsip and dnsip not in currdnsips:
needcfgwrite = True
currdnsips.append(dnsip)
if dnsdomain:
currdnsdomain = self.getcfgarrpath([devname, 'nameservers', 'search'])
if dnsdomain not in currdnsdomain:
needcfgwrite = True
currdnsdomain.append(dnsdomain)
if needcfgwrite:
needcfgapply = True
newcfg = {'network': {'version': 2, 'ethernets': {devname: self.cfgbydev[devname]}}}
oumask = os.umask(0o77)
with open('/etc/netplan/{0}-confluentcfg.yaml'.format(devname), 'w') as planout:
planout.write(yaml.dump(newcfg))
os.umask(oumask)
if needcfgapply:
subprocess.call(['netplan', 'apply'])
def getcfgarrpath(self, devpath):
currptr = self.cfgbydev
for k in devpath[:-1]:
if k not in currptr:
currptr[k] = {}
currptr = currptr[k]
if devpath[-1] not in currptr:
currptr[devpath[-1]] = []
return currptr[devpath[-1]]
class WickedManager(object):
def __init__(self):
self.teamidx = 0
self.read_connections()
def read_connections(self):
self.cfgbydev = {}
for ifcfg in glob.glob('/etc/sysconfig/network/ifcfg-*'):
devname = ifcfg.replace('/etc/sysconfig/network/ifcfg-', '')
if devname == 'lo':
continue
currcfg = {}
self.cfgbydev[devname] = currcfg
for cfg in open(ifcfg).read().splitlines():
cfg = cfg.split('#', 1)[0]
try:
kv = ' '.join(shlex.split(cfg)).split('=', 1)
except Exception:
# unparseable line, likely having something we can't handle
del self.cfgbydev[devname]
if len(kv) != 2:
continue
k, v = kv
k = k.strip()
v = v.strip()
currcfg[k] = v
def apply_configuration(self, cfg):
stgs = cfg['settings']
ipcfg = 'STARTMODE=auto\n'
routecfg = ''
bootproto4 = stgs.get('ipv4_method', 'none')
bootproto6 = stgs.get('ipv6_method', 'none')
if bootproto4 == 'dhcp' and bootproto6 == 'dhcp':
ipcfg += 'BOOTPROTO=dhcp\n'
elif bootproto4 == 'dhcp':
ipcfg += 'BOOTPROTO=dhcp4\n'
elif bootproto6 == 'dhcp':
ipcfg += 'BOOTPROTO=dhcp6\n'
else:
ipcfg += 'BOOTPROTO=static\n'
if stgs.get('ipv4_address', None):
ipcfg += 'IPADDR=' + stgs['ipv4_address'] + '\n'
v4gw = stgs.get('ipv4_gateway', None)
if stgs.get('ipv6_address', None):
ipcfg += 'IPADDR_V6=' + stgs['ipv6_address'] + '\n'
v6gw = stgs.get('ipv6_gateway', None)
cname = None
if len(cfg['interfaces']) > 1: # creating new team
if not stgs.get('team_mode', None):
sys.stderr.write("Warning, multiple interfaces ({0}) without a team_mode, skipping setup\n".format(','.join(cfg['interfaces'])))
return
if not stgs.get('connection_name', None):
stgs['connection_name'] = 'bond{0}'.format(self.teamidx)
self.teamidx += 1
cname = stgs['connection_name']
with open('/etc/sysconfig/network/ifcfg-{0}'.format(cname), 'w') as teamout:
teamout.write(ipcfg)
if stgs['team_mode'] == 'lacp':
stgs['team_mode'] = '802.3ad'
teamout.write("BONDING_MODULE_OPTS='mode={0} miimon=100'\nBONDING_MASTER=yes\n".format(stgs['team_mode']))
idx = 1
for iface in cfg['interfaces']:
subprocess.call(['wicked', 'ifdown', iface])
try:
os.remove('/etc/sysconfig/network/ifcfg-{0}'.format(iface))
os.remove('/etc/sysconfig/network/ifroute-{0}'.format(iface))
except OSError:
pass
teamout.write('BONDING_SLAVE{0}={1}\n'.format(idx, iface))
idx += 1
else:
cname = list(cfg['interfaces'])[0]
priorcfg = self.cfgbydev.get(cname, {})
for cf in priorcfg:
if cf.startswith('TEAM_'):
ipcfg += '{0}={1}\n'.format(cf, priorcfg[cf])
with open('/etc/sysconfig/network/ifcfg-{0}'.format(cname), 'w') as iout:
iout.write(ipcfg)
if v4gw:
routecfg += 'default {0} - {1}\n'.format(v4gw, cname)
if v6gw:
routecfg += 'default {0} - {1}\n'.format(v6gw, cname)
if routecfg:
with open('/etc/sysconfig/network/ifroute-{0}'.format(cname), 'w') as routeout:
routeout.write(routecfg)
subprocess.call(['wicked', 'ifup', cname])
class NetworkManager(object):
bondtypes = {
'lacp': '802.3ad',
'loadbalance': 'balance-alb',
'roundrobin': 'balance-rr',
'activebackup': 'active-backup',
}
def __init__(self, devtypes, deploycfg):
self.deploycfg = deploycfg
self.connections = {}
self.uuidbyname = {}
self.uuidbydev = {}
self.connectiondetail = {}
self.read_connections()
self.teamidx = 0
self.devtypes = devtypes
def read_connections(self):
self.connections = {}
self.uuidbyname = {}
self.uuidbydev = {}
self.connectiondetail = {}
ci = subprocess.check_output(['nmcli', '-t', 'c']).decode('utf8')
for inf in ci.splitlines():
n, u, t, dev = inf.split(':')
if n == 'NAME':
continue
if dev == '--':
dev = None
self.uuidbyname[n] = u
if dev:
self.uuidbydev[dev] = u
self.connections[u] = {'name': n, 'uuid': u, 'type': t, 'dev': dev}
deats = {}
for deat in subprocess.check_output(['nmcli', 'c', 's', u]).decode('utf8').splitlines():
k, v = deat.split(':', 1)
v = v.strip()
if v == '--':
continue
if '(default)' in v:
continue
deats[k] = v
self.connectiondetail[u] = deats
def add_team_member(self, team, member):
bondcfg = {}
if member in self.uuidbydev:
myuuid = self.uuidbydev[member]
deats = self.connectiondetail[myuuid]
currteam = deats.get('connection.master', None)
if currteam == team:
return
for stg in ('ipv4.dhcp-hostname', 'ipv4.dns', 'ipv6.dns', 'ipv6.dhcp-hostname'):
if deats.get(stg, None):
bondcfg[stg] = deats[stg]
if member in self.uuidbyname:
subprocess.check_call(['nmcli', 'c', 'del', self.uuidbyname[member]])
devtype = self.devtypes.get(member, 'bond-slave')
subprocess.check_call(['nmcli', 'c', 'add', 'type', devtype, 'master', team, 'con-name', member, 'connection.interface-name', member])
if bondcfg:
args = []
for parm in bondcfg:
args.append(parm)
args.append(bondcfg[parm])
subprocess.check_call(['nmcli', 'c', 'm', team] + args)
def apply_configuration(self, cfg, lastchance=False):
cmdargs = {}
cmdargs['connection.autoconnect'] = 'yes'
stgs = cfg['settings']
cmdargs['ipv6.method'] = stgs.get('ipv6_method', 'link-local')
if stgs.get('ipv6_address', None):
cmdargs['ipv6.addresses'] = stgs['ipv6_address']
cmdargs['ipv4.method'] = stgs.get('ipv4_method', 'disabled')
if stgs.get('ipv4_address', None):
cmdargs['ipv4.addresses'] = stgs['ipv4_address']
if stgs.get('ipv4_gateway', None):
cmdargs['ipv4.gateway'] = stgs['ipv4_gateway']
if stgs.get('ipv6_gateway', None):
cmdargs['ipv6.gateway'] = stgs['ipv6_gateway']
if stgs.get('mtu', None):
cmdargs['802-3-ethernet.mtu'] = stgs['mtu']
dnsips = self.deploycfg.get('nameservers', [])
if not dnsips:
dnsips = []
dns4 = []
dns6 = []
for dnsip in dnsips:
if '.' in dnsip:
dns4.append(dnsip)
elif ':' in dnsip:
dns6.append(dnsip)
if dns4:
cmdargs['ipv4.dns'] = ','.join(dns4)
if dns6:
cmdargs['ipv6.dns'] = ','.join(dns6)
if len(cfg['interfaces']) > 1: # team time.. should be..
if not cfg['settings'].get('team_mode', None):
sys.stderr.write("Warning, multiple interfaces ({0}) without a team_mode, skipping setup\n".format(','.join(cfg['interfaces'])))
return
if not cfg['settings'].get('connection_name', None):
cfg['settings']['connection_name'] = 'team{0}'.format(self.teamidx)
self.teamidx += 1
cname = cfg['settings']['connection_name']
cargs = []
for arg in cmdargs:
cargs.append(arg)
cargs.append('{}'.format(cmdargs[arg]))
if stgs['team_mode'] in self.bondtypes:
stgs['team_mode'] = self.bondtypes[stgs['team_mode']]
subprocess.check_call(['nmcli', 'c', 'add', 'type', 'bond', 'con-name', cname, 'connection.interface-name', cname, 'bond.options', 'miimon=100,mode={}'.format(stgs['team_mode'])] + cargs)
for iface in cfg['interfaces']:
self.add_team_member(cname, iface)
subprocess.check_call(['nmcli', 'c', 'u', cname])
else:
cname = stgs.get('connection_name', None)
iname = list(cfg['interfaces'])[0]
ctype = self.devtypes.get(iname, None)
if not ctype:
if lastchance:
sys.stderr.write("Warning, no device found for interface_name ({0}), skipping setup\n".format(iname))
return 1
if stgs.get('vlan_id', None):
vlan = stgs['vlan_id']
if ctype == 'infiniband':
vlan = '0x{0}'.format(vlan) if not vlan.startswith('0x') else vlan
cmdargs['infiniband.parent'] = iname
cmdargs['infiniband.p-key'] = vlan
iname = '{0}.{1}'.format(iname, vlan[2:])
elif ctype == 'ethernet':
ctype = 'vlan'
cmdargs['vlan.parent'] = iname
cmdargs['vlan.id'] = vlan
iname = '{0}.{1}'.format(iname, vlan)
else:
sys.stderr.write("Warning, unknown interface_name ({0}) device type ({1}) for VLAN/PKEY, skipping setup\n".format(iname, ctype))
return
cname = iname if not cname else cname
u = self.uuidbyname.get(cname, None)
cargs = []
for arg in cmdargs:
cargs.append(arg)
cargs.append('{}'.format(cmdargs[arg]))
if u:
subprocess.check_call(['nmcli', 'c', 'm', u, 'connection.interface-name', iname] + cargs)
subprocess.check_call(['nmcli', 'c', 'u', u])
else:
subprocess.check_call(['nmcli', 'c', 'add', 'type', ctype, 'con-name', cname, 'connection.interface-name', iname] + cargs)
self.read_connections()
u = self.uuidbyname.get(cname, None)
if u:
subprocess.check_call(['nmcli', 'c', 'u', u])
if __name__ == '__main__':
havefirewall = subprocess.call(['systemctl', 'status', 'firewalld'])
havefirewall = havefirewall == 0
if havefirewall:
subprocess.check_call(['systemctl', 'stop', 'firewalld'])
tmpllas = add_missing_llas()
await_tentative()
idxmap, devtypes = map_idx_to_name()
netname_to_interfaces = {}
myaddrs = apiclient.get_my_addresses()
srvs, _ = apiclient.scan_confluents()
doneidxs = set([])
dc = None
if not srvs: # the multicast scan failed, fallback to deploycfg cfg file
with open('/etc/confluent/confluent.deploycfg', 'r') as dci:
for cfgline in dci.read().split('\n'):
if cfgline.startswith('deploy_server:'):
srvs = [cfgline.split()[1]]
break
for srv in srvs:
try:
s = socket.create_connection((srv, 443))
except socket.error:
continue
myname = s.getsockname()
s.close()
if len(myname) == 4:
curridx = myname[-1]
else:
myname = myname[0]
myname = socket.inet_pton(socket.AF_INET, myname)
for addr in myaddrs:
if myname == addr[1].tobytes():
curridx = addr[-1]
if curridx in doneidxs:
continue
for tries in (1, 2, 3):
try:
status, nc = apiclient.HTTPSClient(usejson=True, host=srv).grab_url_with_status('/confluent-api/self/netcfg')
break
except Exception:
if tries == 3:
raise
time.sleep(1)
continue
nc = json.loads(nc)
if not dc:
for tries in (1, 2, 3):
try:
status, dc = apiclient.HTTPSClient(usejson=True, host=srv).grab_url_with_status('/confluent-api/self/deploycfg2')
break
except Exception:
if tries == 3:
raise
time.sleep(1)
continue
dc = json.loads(dc)
iname = get_interface_name(idxmap[curridx], nc.get('default', {}))
if iname:
for iname in iname.split(','):
if 'default' in netname_to_interfaces:
netname_to_interfaces['default']['interfaces'].add(iname)
else:
netname_to_interfaces['default'] = {'interfaces': set([iname]), 'settings': nc['default']}
for netname in nc.get('extranets', {}):
uname = '_' + netname
iname = get_interface_name(idxmap[curridx], nc['extranets'][netname])
if iname:
for iname in iname.split(','):
if uname in netname_to_interfaces:
netname_to_interfaces[uname]['interfaces'].add(iname)
else:
netname_to_interfaces[uname] = {'interfaces': set([iname]), 'settings': nc['extranets'][netname]}
doneidxs.add(curridx)
if 'default' in netname_to_interfaces:
for netn in netname_to_interfaces:
if netn == 'default':
continue
netname_to_interfaces['default']['interfaces'] -= netname_to_interfaces[netn]['interfaces']
if not netname_to_interfaces['default']['interfaces']:
del netname_to_interfaces['default']
# Make sure VLAN/PKEY connections are created last
netname_to_interfaces = dict(sorted(netname_to_interfaces.items(), key=lambda item: 'vlan_id' in item[1]['settings']))
rm_tmp_llas(tmpllas)
if os.path.exists('/usr/sbin/netplan'):
nm = NetplanManager(dc)
if os.path.exists('/usr/bin/nmcli'):
nm = NetworkManager(devtypes, dc)
elif os.path.exists('/usr/sbin/wicked'):
nm = WickedManager()
retrynics = []
for netn in netname_to_interfaces:
redo = nm.apply_configuration(netname_to_interfaces[netn])
if redo == 1:
retrynics.append(netn)
if retrynics:
idxmap, devtypes = map_idx_to_name()
if os.path.exists('/usr/sbin/netplan'):
nm = NetplanManager(dc)
if os.path.exists('/usr/bin/nmcli'):
nm = NetworkManager(devtypes, dc)
elif os.path.exists('/usr/sbin/wicked'):
nm = WickedManager()
for netn in retrynics:
nm.apply_configuration(netname_to_interfaces[netn], lastchance=True)
if havefirewall:
subprocess.check_call(['systemctl', 'start', 'firewalld'])
await_tentative()
@@ -0,0 +1,11 @@
[Unit]
Description=First Boot Process
Requires=network-online.target
After=network-online.target
[Service]
ExecStart=/opt/confluent/bin/firstboot.sh
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,22 @@
#!/bin/bash
echo "Confluent first boot is running"
HOME=$(getent passwd $(whoami)|cut -d: -f 6)
export HOME
#cp -a /etc/confluent/ssh/* /etc/ssh/
#systemctl restart sshd
rootpw=$(grep ^rootpassword: /etc/confluent/confluent.deploycfg |awk '{print $2}')
if [ ! -z "$rootpw" -a "$rootpw" != "null" ]; then
echo root:$rootpw | chpasswd -e
fi
nodename=$(grep ^NODENAME: /etc/confluent/confluent.info | awk '{print $2}')
confluent_apikey=$(cat /etc/confluent/confluent.apikey)
confluent_mgr=$(grep ^deploy_server: /etc/confluent/confluent.deploycfg |awk '{print $2}')
while ! ping -c 1 $confluent_mgr >& /dev/null; do
sleep 1
done
source /etc/confluent/functions
run_remote_parts firstboot.d
run_remote_config firstboot.d
systemctl disable firstboot
curl -f -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $confluent_apikey" -X POST -d "status: complete" https://$confluent_mgr/confluent-api/self/updatestatus
@@ -0,0 +1,216 @@
#!/bin/bash
function test_mgr() {
whost=$1
if [[ "$whost" == *:* ]] && [[ "$whost" != *[* ]] ; then
whost="[$whost]"
fi
if curl -gs https://${whost}/confluent-api/ > /dev/null; then
return 0
fi
return 1
}
function initconfluentscriptstmp() {
if [ -z "$confluentscripttmpdir" ]; then
mkdir -p /opt/confluent/tmpexec
confluentscripttmpdir=$(mktemp -d /opt/confluent/tmpexec/confluentscripts.XXXXXXXXX)
fi
}
function confluentpython() {
if [ -x /usr/libexec/platform-python ]; then
/usr/libexec/platform-python $*
elif [ -x /usr/bin/python3 ]; then
/usr/bin/python3 $*
elif [ -x /usr/bin/python ]; then
/usr/bin/python $*
elif [ -x /usr/bin/python2 ]; then
/usr/bin/python2 $*
fi
}
function set_confluent_vars() {
if [ -z "$nodename" ]; then
nodename=$(grep ^NODENAME: /etc/confluent/confluent.info | awk '{print $2}')
fi
if [[ "$confluent_mgr" == *"%"* ]]; then
confluent_mgr=""
fi
if [ -z "$confluent_mgr" ]; then
confluent_mgr=$(grep ^deploy_server: /etc/confluent/confluent.deploycfg | sed -e 's/[^ ]*: //')
if ! test_mgr $confluent_mgr; then
confluent_mgr=$(grep ^deploy_server_v6: /etc/confluent/confluent.deploycfg | sed -e 's/[^ ]*: //')
if [[ "$confluent_mgr" = *":"* ]]; then
confluent_mgr="[$confluent_mgr]"
fi
fi
if ! test_mgr $confluent_mgr; then
BESTMGRS=$(grep ^EXTMGRINFO: /etc/confluent/confluent.info | grep '|1$' | sed -e 's/EXTMGRINFO: //' -e 's/|.*//')
OKMGRS=$(grep ^EXTMGRINFO: /etc/confluent/confluent.info | grep '|0$' | sed -e 's/EXTMGRINFO: //' -e 's/|.*//')
for confluent_mgr in $BESTMGRS $OKMGRS; do
if [[ $confluent_mgr == *":"* ]]; then
confluent_mgr="[$confluent_mgr]"
fi
if test_mgr $confluent_mgr; then
break
fi
done
fi
fi
if [ -z "$confluent_profile" ]; then
confluent_profile=$(grep ^profile: /etc/confluent/confluent.deploycfg | sed -e 's/[^ ]*: //')
fi
export confluent_profile confluent_mgr nodename
}
fetch_remote() {
curlargs=""
if [ -f /etc/confluent/ca.pem ]; then
curlargs=" --cacert /etc/confluent/ca.pem"
fi
set_confluent_vars
mkdir -p $(dirname $1)
whost=$confluent_mgr
if [[ "$whost" == *:* ]] && [[ "$whost" != *[* ]] ; then
whost="[$whost]"
fi
curl -gf -sS $curlargs https://$whost/confluent-public/os/$confluent_profile/scripts/$1 > $1
if [ $? != 0 ]; then echo $1 failed to download; return 1; fi
}
source_remote_parts() {
unset confluentscripttmpdir
initconfluentscriptstmp
apiclient=/opt/confluent/bin/apiclient
if [ -f /etc/confluent/apiclient ]; then
apiclient=/etc/confluent/apiclient
fi
scriptlist=$(confluentpython $apiclient /confluent-api/self/scriptlist/$1|sed -e 's/^- //')
for script in $scriptlist; do
source_remote $1/$script
done
rm -rf $confluentscripttmpdir
unset confluentscripttmpdir
}
run_remote_parts() {
unset confluentscripttmpdir
initconfluentscriptstmp
apiclient=/opt/confluent/bin/apiclient
if [ -f /etc/confluent/apiclient ]; then
apiclient=/etc/confluent/apiclient
fi
scriptlist=$(confluentpython $apiclient /confluent-api/self/scriptlist/$1|sed -e 's/^- //')
for script in $scriptlist; do
run_remote $1/$script
done
rm -rf $confluentscripttmpdir
unset confluentscripttmpdir
}
source_remote() {
set_confluent_vars
unsettmpdir=0
echo
echo '---------------------------------------------------------------------------'
echo Sourcing $1 from https://$confluent_mgr/confluent-public/os/$confluent_profile/scripts/
initconfluentscriptstmp
echo Sourcing from $confluentscripttmpdir
cd $confluentscripttmpdir
fetch_remote $1
if [ $? != 0 ]; then echo $1 failed to download; return 1; fi
chmod +x $1
cmd=$1
shift
source ./$cmd
cd - > /dev/null
if [ "$unsettmpdir" = 1 ]; then
rm -rf $confluentscripttmpdir
unset confluentscripttmpdir
unsettmpdir=0
fi
rm -rf $confluentscripttmpdir
return $retcode
}
run_remote() {
requestedcmd="'$*'"
unsettmpdir=0
set_confluent_vars
echo
echo '---------------------------------------------------------------------------'
echo Running $requestedcmd from https://$confluent_mgr/confluent-public/os/$confluent_profile/scripts/
if [ -z "$confluentscripttmpdir" ]; then
unsettmpdir=1
fi
initconfluentscriptstmp
echo Executing in $confluentscripttmpdir
cd $confluentscripttmpdir
fetch_remote $1
if [ $? != 0 ]; then echo $requestedcmd failed to download; return 1; fi
chmod +x $1
cmd=$1
if [ -x /usr/bin/chcon ]; then
chcon system_u:object_r:bin_t:s0 $cmd
fi
shift
./$cmd $*
retcode=$?
if [ $retcode -ne 0 ]; then
echo "$requestedcmd exited with code $retcode"
fi
cd - > /dev/null
if [ "$unsettmpdir" = 1 ]; then
rm -rf $confluentscripttmpdir
unset confluentscripttmpdir
unsettmpdir=0
fi
return $retcode
}
run_remote_python() {
echo
set_confluent_vars
if [ -f /etc/confluent/ca.pem ]; then
curlargs=" --cacert /etc/confluent/ca.pem"
fi
echo '---------------------------------------------------------------------------'
echo Running python script "'$*'" from https://$confluent_mgr/confluent-public/os/$confluent_profile/scripts/
unset confluentscripttmpdir
initconfluentscriptstmp
echo Executing in $confluentscripttmpdir
cd $confluentscripttmpdir
mkdir -p $(dirname $1)
whost=$confluent_mgr
if [[ "$whost" == *:* ]] && [[ "$whost" != *[* ]] ; then
whost="[$whost]"
fi
curl -gf -sS $curlargs https://$whost/confluent-public/os/$confluent_profile/scripts/$1 > $1
if [ $? != 0 ]; then echo "'$*'" failed to download; return 1; fi
confluentpython $*
retcode=$?
echo "'$*' exited with code $retcode"
cd - > /dev/null
rm -rf $confluentscripttmpdir
unset confluentscripttmpdir
return $retcode
}
run_remote_config() {
echo
set_confluent_vars
apiclient=/opt/confluent/bin/apiclient
if [ -f /etc/confluent/apiclient ]; then
apiclient=/etc/confluent/apiclient
fi
echo '---------------------------------------------------------------------------'
echo Requesting to run remote configuration for "'$*'" from $confluent_mgr under profile $confluent_profile
confluentpython $apiclient /confluent-api/self/remoteconfig/"$*" -d {}
confluentpython $apiclient /confluent-api/self/remoteconfig/status -w 204
echo
echo 'Completed remote configuration'
echo '---------------------------------------------------------------------------'
return
}
#If invoked as a command, use the arguments to actually run a function
(return 0 2>/dev/null) || $1 "${@:2}"
+67
View File
@@ -0,0 +1,67 @@
#!/bin/bash
mkdir -p /run/sshd
mkdir -p /root/.ssh
cat /tmp/ssh/*pubkey >> /root/.ssh/authorized_keys
cat /tmp/ssh/*.ca | sed -e s/^/'@cert-authority * '/ >> /etc/ssh/ssh_known_hosts
chmod 700 /etc/confluent
chmod go-rwx /etc/confluent/*
sshconf=/etc/ssh/ssh_config
if [ -d /etc/ssh/ssh_config.d/ ]; then
sshconf=/etc/ssh/ssh_config.d/01-confluent.conf
fi
echo 'Host *' >> $sshconf
echo ' HostbasedAuthentication yes' >> $sshconf
echo ' EnableSSHKeysign yes' >> $sshconf
echo ' HostbasedKeyTypes *ed25519*' >> $sshconf
/usr/sbin/sshd
confluent_profile=$(grep ^profile: /etc/confluent/confluent.deploycfg | awk '{print $2}')
mkdir -p /opt/confluent/bin
python3 /opt/confluent/bin/apiclient /confluent-public/os/$confluent_profile/scripts/firstboot.sh > /opt/confluent/bin/firstboot.sh
chmod +x /opt/confluent/bin/firstboot.sh
python3 /opt/confluent/bin/apiclient /confluent-public/os/$confluent_profile/scripts/firstboot.service > /etc/systemd/system/firstboot.service
systemctl enable firstboot
python3 /opt/confluent/bin/apiclient /confluent-public/os/$confluent_profile/scripts/functions > /etc/confluent/functions
source /etc/confluent/functions
python3 /opt/confluent/bin/apiclient /confluent-api/self/nodelist | sed -e s/'^- //' > /tmp/allnodes
cp /tmp/allnodes /root/.shosts
cp /tmp/allnodes /etc/ssh/shosts.equiv
if grep ^ntpservers: /etc/confluent/confluent.deploycfg > /dev/null; then
ntps=$(sed -n '/^ntpservers:/,/^[^-]/p' /etc/confluent/confluent.deploycfg|sed 1d|sed '$d' | sed -e 's/^- //' | paste -sd ' ')
sed -i "s/#NTP=/NTP=$ntps/" /etc/systemd/timesyncd.conf
fi
textcons=$(grep ^textconsole: /etc/confluent/confluent.deploycfg |awk '{print $2}')
updategrub=0
if [ "$textcons" = "true" ] && ! grep console= /proc/cmdline > /dev/null; then
cons=""
if [ -f /tmp/autocons.info ]; then
cons=$(cat /tmp/autocons.info)
fi
if [ ! -z "$cons" ]; then
sed -i 's/GRUB_CMDLINE_LINUX="\([^"]*\)"/GRUB_CMDLINE_LINUX="\1 console='${cons#/dev/}'"/' /etc/default/grub
updategrub=1
fi
fi
kargs=$(python3 /opt/confluent/bin/apiclient /confluent-public/os/$confluent_profile/profile.yaml | grep ^installedargs: | sed -e 's/#.*//')
if [ ! -z "$kargs" ]; then
sed -i 's/GRUB_CMDLINE_LINUX="\([^"]*\)"/GRUB_CMDLINE_LINUX="\1 '"${kargs}"'"/' /etc/default/grub
fi
if [ 1 = $updategrub ]; then
update-grub
fi
if [ -e /sys/firmware/efi ]; then
bootnum=$(efibootmgr | grep ubuntu | sed -e 's/ .*//' -e 's/\*//' -e s/Boot//)
if [ ! -z "$bootnum" ]; then
currboot=$(efibootmgr | grep ^BootOrder: | awk '{print $2}')
nextboot=$(echo $currboot| awk -F, '{print $1}')
[ "$nextboot" = "$bootnum" ] || efibootmgr -o $bootnum,$currboot
efibootmgr -D
fi
fi
run_remote_python syncfileclient
run_remote_parts post.d
run_remote_config post
python3 /opt/confluent/bin/apiclient /confluent-api/self/updatestatus -d 'status: staged'
+88
View File
@@ -0,0 +1,88 @@
#!/bin/sh
## Use the following option to add additional boot parameters for the
## installed system (if supported by the bootloader installer).
## Note: options passed to the installer will be added automatically.
#d-i debian-installer/add-kernel-opts string [from profile.yaml]
deploycfg=/etc/confluent/confluent.deploycfg
mgr=$(cat /etc/confluent/deployer)
cryptboot=$(grep encryptboot: $deploycfg|sed -e 's/^encryptboot: //')
if [ "$cryptboot" != "" ] && [ "$cryptboot" != "none" ] && [ "$cryptboot" != "null" ]; then
echo "****Encrypted boot requested, but not implemented for this OS, halting install" > /dev/console
[ -f '/tmp/autoconsdev' ] && (echo "****Encryptod boot requested, but not implemented for this OS,halting install" >> $(cat /tmp/autoconsdev))
while :; do sleep 86400; done
fi
cat > /usr/lib/live-installer.d/confluent-certs << EOF
#!/bin/sh
cp /tls/* /target/etc/ssl/certs/
cat /tls/*.pem >> /target/etc/ssl/certs/ca-certificates.crt
EOF
chmod a+x /usr/lib/live-installer.d/confluent-certs
mkdir -p /.ssh/
cat /ssh/*pubkey > /.ssh/authorized_keys
mkdir -p /etc/ssh
nodename=$(grep ^NODENAME: /etc/confluent/confluent.info|cut -d ' ' -f 2)
apikey=$(cat /etc/confluent/confluent.apikey)
ssh-keygen -A
for pubkey in /etc/ssh/ssh_host*key.pub; do
certfile=$(echo $pubkey | sed -e s/.pub/-cert.pub/)
keyfile=${pubkey%.pub}
wget --header="CONFLUENT_NODENAME: $nodename" --header="CONFLUENT_APIKEY: $apikey" --post-file=$pubkey https://$mgr/confluent-api/self/sshcert -O $certfile --quiet
echo HostKey $keyfile >> /etc/ssh/sshd_config
echo HostCertificate $certfile >> /etc/ssh/sshd_config
done
if [ -e /tmp/installdisk ]; then
instdisk=$(cat /tmp/installdisk)
else
for blockdev in $(ls /sys/class/block/); do
shortname=$(basename $blockdev)
if [ "$shortname" != "${shortname%loop*}" ]; then
continue
fi
udevadm info --query=property /dev/$shortname |grep DEVTYPE=disk > /dev/null || continue # ignore partitions
udevadm info --query=property /dev/$shortname |grep DM_NAME > /dev/null && continue # not a real disk
sz=$(cat /sys/block/$shortname/size 2> /dev/null)
[ -z "$sz" ] && continue
[ $sz -lt 1048576 ] && continue # Too small
[ -z "$firstdisk" ] && firstdisk=$shortname
if udevadm info --query=property /dev/$shortname|grep ID_MODEL=| sed -e s/' '/_/g | grep -iE '(thinksystem_m.2|m.2_nvme_2-bay_raid_kit)' > /dev/null; then
instdisk=$shortname
break
fi
if udevadm info --query=property /dev/$shortname|grep MD_CONTAINER=imsm; then
sraid=$sortname
else
drv=$(udevadm info -a /dev/sdb|grep DRIVERS==|grep -Ev '""|"sd"' | sed -e s/.*=// -e s/'"'//g)
if [ "ahci" = "$drv" -a -z "$onbdisk" ]; then
onbdisk=$shortname
elif [ "megaraid" = "$drv" -a -z "$rdisk" ]; then
rdisk=$shortname
fi
fi
done
fi
if [ -z "$instdisk" ]; then
if [ ! -z "$sraid"]; then
instdisk=$sraid
elif [ ! -z "$onbdisk" ]; then
instdisk=$onbdisk
elif [ ! -z "$rdisk" ]; then
instdisk=$rdisk
else
instdisk=$firstdisk
fi
fi
if [ ! -z "$instdisk" ]; then
debconf-set partman-auto/disk /dev/$instdisk
debconf-set grub-installer/bootdev /dev/$instdisk
fi
echo HostbasedAuthentication yes >> /etc/ssh/sshd_config
echo HostbasedUsesNameFromPacketOnly yes >> /etc/ssh/sshd_config
echo IgnoreRhosts no >> /etc/ssh/sshd_config
echo sshd:x:1:1::/run/sshd:/bin/false >> /etc/passwd
/usr/sbin/sshd
wget --header="CONFLUENT_NODENAME: $nodename" --header="CONFLUENT_APIKEY: $apikey" https://$mgr/confluent-api/self/nodelist -O /tmp/allnodes --quiet
#kill -HUP $(ps | grep -v grep | grep /usr/sbin/sshd | sed -e 's/^ *//'|cut -d ' ' -f 1)
#curl -f https://$confluent_mgr/confluent-public/os/$confluent_profile/scripts/getinstalldisk > /tmp/getinstalldisk
#python3 /tmp/getinstalldisk
#sed -i s!%%INSTALLDISK%%!/dev/$(cat /tmp/installdisk)! /autoinstall.yaml

Some files were not shown because too many files have changed in this diff Show More