Sync from SUSE:SLFO:Main hyper-v revision 74247cac645ac33682f133879d6a5715

This commit is contained in:
Adrian Schröter 2024-05-03 13:38:15 +02:00
commit 85293fbb38
14 changed files with 4776 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

507
hyper-v.changes Normal file
View File

@ -0,0 +1,507 @@
-------------------------------------------------------------------
Thu Aug 20 12:12:12 UTC 2020 - ohering@suse.de
- Allow daemon restart again (bsc#1116957)
Since some time the kernel moved from netlink sockets to char
devices, which is supposed to handle a connection reopen for the
kernel<->daemon interface
-------------------------------------------------------------------
Wed Jul 22 12:12:12 UTC 2020 - ohering@suse.de
- Remove dependency to network-online.target now that gethostname
is used in kvp_daemon (bsc#1174443, bsc#1174444)
- Reopen the devices if read() or write() returns errors (9fc3c01a)
- Use either python2 or python3 for lsvmbus (bsc#1093910)
- Remove sysv init scripts
-------------------------------------------------------------------
Wed Jul 22 09:12:44 UTC 2020 - Guillaume GARDET <guillaume.gardet@opensuse.org>
- Enable build on aarch64
-------------------------------------------------------------------
Thu Feb 20 16:16:16 UTC 2020 - ohering@suse.de
- Revert previous non-upstream change for async name resolution
Just use gethostname via hyper-v.kvp.gethostname.patch (bsc#1100758)
-------------------------------------------------------------------
Fri Nov 29 16:41:25 UTC 2019 - ohering@suse.de
- Update lsvmbus interpreter from python(1) to python3(1) again
because only SLE12 lacked proper python3 support (bsc#1093910)
-------------------------------------------------------------------
Wed Nov 27 09:08:07 UTC 2019 - ohering@suse.de
- async name resolution in kvp_daemon (bsc#1100758)
- kvp: eliminate 'may be used uninitialized' warning (89eb4d8d)
- fix typos in toolchain (2d35c660)
- fixed Python pep8/flake8 warnings for lsvmbus (5912e791)
- Replace GPLv2 boilerplate/reference with SPDX (43aa3132)
- Fix a warning of buffer overflow with gcc 8.0.1 (4fcba780)
-------------------------------------------------------------------
Tue Oct 9 09:27:45 UTC 2018 - ohering@suse.de
- fcopy: set 'error' in case an unknown operation was requested (c2d68afb)
-------------------------------------------------------------------
Mon Oct 8 06:48:04 UTC 2018 - ohering@suse.de
- Update lsvmbus interpreter from python3(1) to python(1)
because SLE12 lacks python3 support (bsc#1093910)
-------------------------------------------------------------------
Tue Sep 25 08:33:36 UTC 2018 - ohering@suse.de
- vss: fix loop device detection (07136793)
- Fix IP reporting by KVP daemon with SRIOV (4ba63412)
- Fix a bug in the key delete code (86503bd3)
- fix compiler warnings about major/target_fname (1330fc35)
- PRIVATE hyper-v.compare-with-upstream.sh
-------------------------------------------------------------------
Thu Aug 2 08:46:52 UTC 2018 - schwab@suse.de
- hyper-v.tools.hv.hv_vss_daemon.c: Include <sys/sysmacros.h> for major
-------------------------------------------------------------------
Tue May 22 06:56:57 UTC 2018 - ohering@suse.de
- Update lsvmbus interpreter from env(1) to python3(1) (bsc#1093910)
-------------------------------------------------------------------
Mon Jan 8 10:45:35 UTC 2018 - ohering@suse.de
- update buffer handling in hv_fcopy_daemon
- remove unnecessary header files and netlink related code
- Avoid reading past allocated blocks from KVP file (bnc#1087658)
- fix snprintf warning in kvp_daemon
- properly handle long paths
- kvp: configurable external scripts path
- vss: Thaw the filesystem and continue if freeze call has timed out
- vss: Skip freezing filesystems backed by loop
-------------------------------------------------------------------
Wed Jun 28 12:04:38 UTC 2017 - ohering@suse.de
- Check VSS daemon is listening before a hot backup (bnc#1029693)
- fix a compile warning in snprintf
- kvp: ensure kvp device fd is closed on exec
- lsvmbus: add pci pass-through UUID
-------------------------------------------------------------------
Wed May 4 13:29:54 UTC 2016 - ohering@suse.de
- add Conflicts with kernel < 4.2 (fate#320485)
- vss: fix the write()'s argument: error -> vss_msg
- remove repeated HV_FCOPY string
- report ENOSPC errors in hv_fcopy_daemon
- fcopy: full handshake support
- vss: full handshake support
- vss: use misc char device to communicate with kernel
- kvp: use misc char device to communicate with kernel
-------------------------------------------------------------------
Fri Sep 18 10:11:01 UTC 2015 - ohering@suse.de
- add a python script lsvmbus to list VMBus devices (fate#315887)
-------------------------------------------------------------------
Thu Apr 30 11:25:47 UTC 2015 - ohering@suse.de
- hv: hypervvssd: call endmntent before call setmntent again
- remove unused bytes_written from kvp_update_file()
- address compiler warnings for hv_kvp_daemon.c
- kvp_daemon: make IPv6-only-injection work
- address compiler warnings for hv_fcopy_daemon.c
- do not add redundant '/' in hv_start_fcopy()
-------------------------------------------------------------------
Thu Apr 16 15:23:18 UTC 2015 - ohering@suse.de
- Add runlevel script for fcopy daemon in SLE11 (bnc#926534)
-------------------------------------------------------------------
Mon Jan 12 09:37:40 UTC 2015 - ohering@suse.de
- Check return value of setsockopt call
- Improve error logging in VSS daemon.
- Check return value of poll call
- Properly pack the data for file copy functionality
- make struct hv_do_fcopy match Hyper-V host messages
-------------------------------------------------------------------
Wed Dec 17 09:06:33 UTC 2014 - ohering@suse.de
- Start hv_kvp_daemon after network-online.target (bnc#910353)
- ignore ENOBUFS and ENOMEM in the KVP daemon
- vssdaemon: skip all filesystems mounted readonly (bnc#909864)
- vssdaemon: report freeze errors
-------------------------------------------------------------------
Tue Nov 25 17:46:30 UTC 2014 - ohering@suse.de
- introduce -n/--no-daemon option (fate#317533)
-------------------------------------------------------------------
Sun Nov 09 04:39:00 UTC 2014 - Led <ledest@gmail.com>
- fix bashisms in pre/post scripts
-------------------------------------------------------------------
Tue Sep 30 15:41:02 UTC 2014 - ohering@suse.de
- vssdaemon: ignore the EBUSY on multiple freezing the same
partition (bnc#899204)
-------------------------------------------------------------------
Tue Jul 1 17:32:30 CEST 2014 - ohering@suse.de
- fix file overwriting of hv_fcopy_daemon
-------------------------------------------------------------------
Mon May 26 15:50:21 CEST 2014 - ohering@suse.de
- copy mask2pfxlen from /etc/sysconfig/network/scripts/functions
to hv_set_ifconfig (bnc#879256)
-------------------------------------------------------------------
Wed May 21 12:05:31 CEST 2014 - ohering@suse.de
- Start hyper-v helpers manually with helper script in inst-sys
-------------------------------------------------------------------
Thu Apr 10 19:19:04 CEST 2014 - ohering@suse.de
- Handle the case when the target file exists correctly in hv_fcopy_daemon
- vssdaemon: Ignore VFAT mounts during the Freeze operation
-------------------------------------------------------------------
Sun Mar 2 18:11:31 CET 2014 - ohering@suse.de
- Package /usr/lib/udev to fix build error
-------------------------------------------------------------------
Wed Feb 12 10:32:54 CET 2014 - ohering@suse.de
- Update hv_fcopy_daemon, kernel name changed to /dev/vmbus/hv_fcopy
-------------------------------------------------------------------
Thu Jan 23 17:00:54 CET 2014 - ohering@suse.de
- Start daemons on demand via udev rules because the guest services
are optional.
- If systemd is used daemons live in libdir, they are not usercallable apps
-------------------------------------------------------------------
Thu Jan 16 11:09:34 CET 2014 - ohering@suse.de
- Add hv_fcopy_daemon for post 13.1 releases (fate#315887)
hyper-v.tools.hv.hv_fcopy_daemon.c
-------------------------------------------------------------------
Wed Dec 18 14:46:37 CET 2013 - ohering@suse.de
- Use native systemd services for post 13.1 releases
-------------------------------------------------------------------
Sun Sep 8 10:36:29 CEST 2013 - ohering@suse.de
- Update Supplements: modalias(dmi:*)
-------------------------------------------------------------------
Mon Aug 12 16:56:08 CEST 2013 - ohering@suse.de
- Skip restart_on_update with old hyper-v.rpms while old
kernel is running (bnc#770763)
-------------------------------------------------------------------
Wed Aug 7 19:04:35 CEST 2013 - ohering@suse.de
- cache FQDN in kvp_daemon to avoid timeouts (bnc#828714)
- use full nlmsghdr in netlink_send
- correct payload size in netlink_send
- use single send+recv buffer
- log errors to syslog in kvp_set_ip_info
- check return value of system in hv_kvp_daemon
- in kvp_set_ip_info free mac_addr right after usage
- check return value of daemon to fix compiler warning.
-------------------------------------------------------------------
Thu Aug 1 14:21:57 CEST 2013 - ohering@suse.de
- Fix send/recv buffer allocation (bnc#828714)
-------------------------------------------------------------------
Wed Jul 24 10:18:34 CEST 2013 - ohering@suse.de
- set BOOTPROTO=static if any IPADDR/IP6ADDR was passed to
hv_set_ifconfig and dhcp is disabled
-------------------------------------------------------------------
Mon Jul 15 16:16:06 CEST 2013 - ohering@suse.de
- update hv_kvp_daemon (merge 0783d72fa from v3.9-rc1)
Fix how ifcfg-* file is created
-------------------------------------------------------------------
Mon Jul 15 15:24:00 CEST 2013 - ohering@suse.de
- update hv_kvp_daemon (changes up to 3.11-rc1):
Improve error logging in KVP daemon.
Fix file descriptor leaks
Check retrun value of strchr call
Check return value of poll call
Check return value of setsockopt call
daemon should check type of received Netlink msg
daemon setsockopt should use options macros
daemon should subscribe only to CN_KVP_IDX group
-------------------------------------------------------------------
Mon Jul 15 12:04:05 CEST 2013 - ohering@suse.de
- Fix a bug in IPV6 subnet enumeration (bnc#828714)
-------------------------------------------------------------------
Tue Mar 26 18:03:47 CET 2013 - ohering@suse.de
- Update hv_vss_daemon (bnc#811033)
-------------------------------------------------------------------
Fri Mar 22 17:23:36 CET 2013 - ohering@suse.de
- add hv_vss_daemon (fate#314921)
helper to support host initiated backup
-------------------------------------------------------------------
Fri Mar 22 16:56:57 CET 2013 - ohering@suse.de
- build hv_kvp_daemon with -D_GNU_SOURCE to get O_CLOEXEC
-------------------------------------------------------------------
Fri Mar 22 16:19:38 CET 2013 - ohering@suse.de
- update hv_kvp_daemon
Use CLOEXEC when opening kvp_pool files
Fix permissions of created directory and files
Fix /var subdirectory (move state files from /var/opt to /var/lib)
Fix string types
-------------------------------------------------------------------
Tue Nov 27 11:19:32 CET 2012 - ohering@suse.de
- update hv_set_ifconfig, use single index for static ipv4/ipv6 [bnc#790469]
-------------------------------------------------------------------
Sun Nov 25 17:50:40 CET 2012 - ohering@suse.de
- update hv_set_ifconfig further to work with our ifcfg [bnc#790469]
-------------------------------------------------------------------
Thu Nov 22 18:14:12 CET 2012 - ohering@suse.de
- update hv_get_dhcp_info to work with our ifcfg [bnc#790469]
- remove cat usage from hv_get_dns_info
- add quoting to hv_set_ifconfig to make it more robust
-------------------------------------------------------------------
Mon Nov 12 17:18:25 CET 2012 - ohering@suse.de
- remove code to build kmp, it was not enabled because the
drivers are now in kernel since a long time. [bnc#676890]
-------------------------------------------------------------------
Thu Nov 8 14:30:05 CET 2012 - ohering@suse.de
- Netlink source address validation allows DoS [bnc#791605, CVE-2012-5532]
bugfix for recvfrom check from bnc#761200
-------------------------------------------------------------------
Fri Oct 26 17:13:40 CEST 2012 - ohering@suse.de
- update hv_set_ifconfig to work with our ifcfg
-------------------------------------------------------------------
Sat Oct 13 11:40:30 CEST 2012 - ohering@suse.de
- update hv_kvp_daemon
Return the full kernel version
Don't return loopback addresses
-------------------------------------------------------------------
Thu Oct 4 15:14:05 CEST 2012 - ohering@suse.de
- bump to version 4
- update kv_kvp_daemon to 3.7-rc1 state [fate#314441]
support KVP IP Injection, helper scripts go to /usr/lib/hyper-v/bin:
hv_get_dhcp_info, hv_get_dns_info, hv_set_ifconfig
- remove usage of absolute paths in runlevel script
-------------------------------------------------------------------
Tue Sep 4 14:55:38 CEST 2012 - ohering@suse.de
- remove restart_on_update in postun section
the daemon can not be restarted at this point, and the new daemon
may not be 100 percent compatible with the currently running
kernel [bnc#770763]
-------------------------------------------------------------------
Wed May 16 20:44:36 CEST 2012 - ohering@suse.de
- check origin of netlink messages, use recvfrom() [bnc#761200, CVE-2012-2669]
-------------------------------------------------------------------
Wed May 2 12:13:03 CEST 2012 - ohering@suse.de
- update insserv part, see comments in OBS submit request #112701
-------------------------------------------------------------------
Tue Mar 27 08:50:43 CEST 2012 - ohering@suse.de
- add kvptest.ps1.txt to docs, a PowerShell script to verify KVP
-------------------------------------------------------------------
Mon Mar 26 19:05:48 CEST 2012 - ohering@suse.de
- update hv_kvp_daemon to 3.4-rc1 state
use a copy linux/hyperv.h to compile the daemon
-------------------------------------------------------------------
Thu Dec 8 17:46:21 CET 2011 - ohering@suse.de
- do not package modprobe.conf rule in main package
prevents loading of ata_piix which is required for cdrom access
-------------------------------------------------------------------
Fri Nov 18 21:49:57 CET 2011 - ohering@suse.de
- add Supplements to install package if dmi matches [bnc#731198]
-------------------------------------------------------------------
Thu Sep 1 18:51:03 CEST 2011 - ohering@suse.de
- disable hyper-v-kmp
hv_storvsc handles now IDE and SCSI disks and ata_piix is
compiled into the kernel in SLE12, so the modprobe.conf rules
have no meaning anymore
-------------------------------------------------------------------
Tue Jul 26 21:24:25 CEST 2011 - ohering@suse.de
- update hv_kvp_daemon: Cleanup kvp_get_domain_name(). If
getaddrinfo() fails, deal with it properly (this can happen if no
IP address has been assigned). Also, don't specify a specific
service in the call to getaddrinfo() to make this code as generic
as possible.
-------------------------------------------------------------------
Sun Jul 24 17:22:41 CEST 2011 - ohering@suse.de
- update hv_kvp_daemon: The current win7 host does not like it when
we return the complete kernel release information. Conform to
what the host expects.
-------------------------------------------------------------------
Fri Jun 17 15:41:33 CEST 2011 - ohering@suse.de
- update preun, stop_on_removal requires an argument
-------------------------------------------------------------------
Fri Jun 17 11:09:30 CEST 2011 - ohering@suse.de
- remove get_release_number.sh, which was added by accident
- bump version number to 2
-------------------------------------------------------------------
Fri Jun 17 10:58:42 CEST 2011 - ohering@suse.de
- catch errors from daemon()
-------------------------------------------------------------------
Fri Jun 17 10:33:50 CEST 2011 - ohering@suse.de
- update postun to run restart_on_update
- use rpmmacro for daemon name
-------------------------------------------------------------------
Fri Jun 17 08:10:12 CEST 2011 - ohering@suse.de
- update postin to work in / again when running insserv macro
-------------------------------------------------------------------
Thu Jun 16 15:33:49 CEST 2011 - ohering@suse.de
- Update version number to 1 so kernel.rpm can obsolete
the old kmp packages
-------------------------------------------------------------------
Thu Jun 16 11:12:06 CEST 2011 - ohering@suse.de
- enable hv_kvp_daemon if run in a hv guest [fate#312213]
-------------------------------------------------------------------
Thu Apr 21 17:18:20 CEST 2011 - ohering@suse.de
- add hv_kvp_daemon to provide system infos to hypervisor [bnc#685189]
this enables the hyper-v main package
-------------------------------------------------------------------
Sat Apr 16 15:13:36 CEST 2011 - ohering@suse.de
- Require at least kernel-default 2.6.32.27 for an empty KMP.
-------------------------------------------------------------------
Fri Apr 15 16:50:25 CEST 2011 - ohering@suse.de
- actually keep the KMP packages with just the modprobe.conf file
-------------------------------------------------------------------
Thu Mar 31 11:24:03 CEST 2011 - ohering@suse.de
- make building of kernel modules optional [bnc#676890]
the hv*.ko drivers exist in two places, kernel-default and this
KMP package. Both can get out of sync, then mkinitrd will use
(the possible outdated) drivers from this KMP package.
disable building drivers per default, keep only the
hyperv_pvdrivers.conf
- mark hyperv_pvdrivers.conf as config to preserve local
modifications done by the sysadmin
-------------------------------------------------------------------
Thu Feb 24 12:09:25 CET 2011 - meissner@suse.de
- also add hv_timesource to Modules.supported [bnc#650748]
-------------------------------------------------------------------
Tue Jan 4 10:28:21 CET 2011 - meissner@suse.de
- add hv_utils to Modules.supported [bnc#650748]
-------------------------------------------------------------------
Wed Apr 28 11:40:33 CEST 2010 - kukuk@suse.de
- Next update of hyperv_pvdrivers.conf [bnc#600212]
-------------------------------------------------------------------
Tue Apr 27 13:20:55 CEST 2010 - kukuk@suse.de
- hyperv_pvdrivers.conf: fix syntax error
-------------------------------------------------------------------
Tue Apr 27 07:10:05 CEST 2010 - ksrinivasan@novell.com
- Update hyperv_pvdrivers.conf config file
-------------------------------------------------------------------
Mon Apr 26 18:15:40 CEST 2010 - kukuk@suse.de
- Add hyperv_pvdrivers.conf modprobe config file
-------------------------------------------------------------------
Fri Mar 5 13:40:56 CET 2010 - mmarek@suse.cz
- Packaged drivers/staging/hv as a standalone KMP (bnc#585651).

View File

@ -0,0 +1,6 @@
d=~/work/src/kernel/kerncvs.kernel.master
diff -u hyper-v.tools.hv.hv_vss_daemon.c ${d}/tools/hv/hv_vss_daemon.c
diff -u hyper-v.tools.hv.hv_kvp_daemon.c ${d}/tools/hv/hv_kvp_daemon.c
diff -u hyper-v.tools.hv.hv_fcopy_daemon.c ${d}/tools/hv/hv_fcopy_daemon.c
diff -u hyper-v.include.linux.hyperv.h ${d}/include/uapi/linux/hyperv.h
diff -u hyper-v.lsvmbus.py ${d}/tools/hv/lsvmbus

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
--- a/hyper-v.tools.hv.hv_kvp_daemon.c
+++ b/hyper-v.tools.hv.hv_kvp_daemon.c
@@ -1335,6 +1335,7 @@ kvp_get_domain_name(char *buffer, int le
struct addrinfo hints, *info ;
int error = 0;
+ return;
gethostname(buffer, length);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
@@ -1572,6 +1573,12 @@ int main(int argc, char *argv[])
switch (hv_msg->body.kvp_enum_data.index) {
case FullyQualifiedDomainName:
+ /*
+ * The API is undocumented.
+ * The Host can not possibly care about DNS within the guest network
+ * The time it takes to get the hostname is much shorter than a DNS lookup.
+ */
+ gethostname(full_domain_name, sizeof(full_domain_name));
strcpy(key_value, full_domain_name);
strcpy(key_name, "FullyQualifiedDomainName");
break;

49
hyper-v.kvptest.ps1.txt Normal file
View File

@ -0,0 +1,49 @@
# Windows PowerShell script to test Key Value Pair functionality
#
# http://blogs.msdn.com/b/virtual_pc_guy/archive/2008/11/18/hyper-v-script-looking-at-kvp-guestintrinsicexchangeitems.aspx
#
# Per default execution of scripts is disabled.
# http://technet.microsoft.com/en-us/library/ee176949.aspx
# The command 'Set-ExecutionPolicy RemoteSigned' will enable it.
#
# Filter for parsing XML data
filter Import-CimXml
{
# Create new XML object from input
$CimXml = [Xml]$_
$CimObj = New-Object -TypeName System.Object
# Iterate over the data and pull out just the value name and data for each entry
foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Name']"))
{
$CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
}
foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Data']"))
{
$CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
}
# Display output
$CimObj
}
# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
# Prompt for the virtual machine to use
$VMName = Read-Host "Specify the name of the virtual machine"
# Get the virtual machine object
$query = "Select * From Msvm_ComputerSystem Where ElementName='" + $VMName + "'"
$Vm = gwmi -namespace root\virtualization -query $query -computername $HyperVServer
# Get the KVP Object
$query = "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$Kvp = gwmi -namespace root\virtualization -query $query -computername $HyperVServer
Write-Host
Write-Host "Guest KVP information for" $VMName
# Filter the results
$Kvp.GuestIntrinsicExchangeItems | Import-CimXml

112
hyper-v.lsvmbus.py Normal file
View File

@ -0,0 +1,112 @@
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0
import os
from optparse import OptionParser
help_msg = "print verbose messages. Try -vv, -vvv for more verbose messages"
parser = OptionParser()
parser.add_option(
"-v", "--verbose", dest="verbose", help=help_msg, action="count")
(options, args) = parser.parse_args()
verbose = 0
if options.verbose is not None:
verbose = options.verbose
vmbus_sys_path = '/sys/bus/vmbus/devices'
if not os.path.isdir(vmbus_sys_path):
print("%s doesn't exist: exiting..." % vmbus_sys_path)
exit(-1)
vmbus_dev_dict = {
'{0e0b6031-5213-4934-818b-38d90ced39db}': '[Operating system shutdown]',
'{9527e630-d0ae-497b-adce-e80ab0175caf}': '[Time Synchronization]',
'{57164f39-9115-4e78-ab55-382f3bd5422d}': '[Heartbeat]',
'{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}': '[Data Exchange]',
'{35fa2e29-ea23-4236-96ae-3a6ebacba440}': '[Backup (volume checkpoint)]',
'{34d14be3-dee4-41c8-9ae7-6b174977c192}': '[Guest services]',
'{525074dc-8985-46e2-8057-a307dc18a502}': '[Dynamic Memory]',
'{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}': 'Synthetic mouse',
'{f912ad6d-2b17-48ea-bd65-f927a61c7684}': 'Synthetic keyboard',
'{da0a7802-e377-4aac-8e77-0558eb1073f8}': 'Synthetic framebuffer adapter',
'{f8615163-df3e-46c5-913f-f2d2f965ed0e}': 'Synthetic network adapter',
'{32412632-86cb-44a2-9b5c-50d1417354f5}': 'Synthetic IDE Controller',
'{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}': 'Synthetic SCSI Controller',
'{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}': 'Synthetic fiber channel adapter',
'{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}': 'Synthetic RDMA adapter',
'{44c4f61d-4444-4400-9d52-802e27ede19f}': 'PCI Express pass-through',
'{276aacf4-ac15-426c-98dd-7521ad3f01fe}': '[Reserved system device]',
'{f8e65716-3cb3-4a06-9a60-1889c5cccab5}': '[Reserved system device]',
'{3375baf4-9e15-4b30-b765-67acb10d607b}': '[Reserved system device]',
}
def get_vmbus_dev_attr(dev_name, attr):
try:
f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
lines = f.readlines()
f.close()
except IOError:
lines = []
return lines
class VMBus_Dev:
pass
vmbus_dev_list = []
for f in os.listdir(vmbus_sys_path):
vmbus_id = get_vmbus_dev_attr(f, 'id')[0].strip()
class_id = get_vmbus_dev_attr(f, 'class_id')[0].strip()
device_id = get_vmbus_dev_attr(f, 'device_id')[0].strip()
dev_desc = vmbus_dev_dict.get(class_id, 'Unknown')
chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
chn_vp_mapping = sorted(
chn_vp_mapping, key=lambda c: int(c.split(':')[0]))
chn_vp_mapping = [
'\tRel_ID=%s, target_cpu=%s' %
(c.split(':')[0], c.split(':')[1]) for c in chn_vp_mapping
]
d = VMBus_Dev()
d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
d.vmbus_id = vmbus_id
d.class_id = class_id
d.device_id = device_id
d.dev_desc = dev_desc
d.chn_vp_mapping = '\n'.join(chn_vp_mapping)
if d.chn_vp_mapping:
d.chn_vp_mapping += '\n'
vmbus_dev_list.append(d)
vmbus_dev_list = sorted(vmbus_dev_list, key=lambda d: int(d.vmbus_id))
format0 = '%2s: %s'
format1 = '%2s: Class_ID = %s - %s\n%s'
format2 = '%2s: Class_ID = %s - %s\n\tDevice_ID = %s\n\tSysfs path: %s\n%s'
for d in vmbus_dev_list:
if verbose == 0:
print(('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc))
elif verbose == 1:
print(
('VMBUS ID ' + format1) %
(d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
)
else:
print(
('VMBUS ID ' + format2) %
(
d.vmbus_id, d.class_id, d.dev_desc,
d.device_id, d.sysfs_path, d.chn_vp_mapping
)
)

270
hyper-v.spec Normal file
View File

@ -0,0 +1,270 @@
#
# spec file for package hyper-v
#
# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
%define hv_kvp_daemon hv_kvp_daemon
%define hv_vss_daemon hv_vss_daemon
%define hv_fcopy_daemon hv_fcopy_daemon
%define helper_dir /usr/lib/%{name}
Name: hyper-v
ExclusiveArch: %ix86 x86_64 aarch64
%{?systemd_requires}
BuildRequires: pkgconfig(systemd)
# Due to usage of char device instead of netlink
Conflicts: kernel < 4.2
Summary: Microsoft Hyper-V tools
License: GPL-2.0-only
Group: System/Kernel
Supplements: modalias(dmi:*svnMicrosoftCorporation*pnVirtualMachine*rnVirtualMachine*)
Supplements: modalias(pci:v00001414d00005353sv*sd*bc*sc*i*)
Url: http://www.kernel.org
# Arbitrary version number
Version: 8
Release: 0
Source0: hyper-v.lsvmbus.py
Source5: hyper-v.kvptest.ps1.txt
Source7: hyper-v.compare-with-upstream.sh
Source9: hyper-v.include.linux.hyperv.h
Source10: hyper-v.tools.hv.hv_kvp_daemon.c
Source12: hyper-v.tools.hv.hv_vss_daemon.c
Source14: hyper-v.tools.hv.hv_fcopy_daemon.c
Source20: hyper-v.tools.hv.hv_get_dhcp_info.sh
Source21: hyper-v.tools.hv.hv_get_dns_info.sh
Source22: hyper-v.tools.hv.hv_set_ifconfig.sh
Patch0: hyper-v.kvp.gethostname.patch
%description
This package contains the Microsoft Hyper-V tools.
%prep
%setup -Tc
cp -avL %{S:5} kvptest.ps1.txt
cp -vL %{S:9} %{hv_kvp_daemon}.h
cp -vL %{S:10} .
cp -vL %{S:12} %{hv_vss_daemon}.c
cp -vL %{S:14} %{hv_fcopy_daemon}.c
%patch0 -p1
mv `basename %{S:10}` %{hv_kvp_daemon}.c
%build
sed -i~ '/#include <linux.hyperv.h>/d' %{hv_kvp_daemon}.c
sed -i~ '/#include <linux.hyperv.h>/d' %{hv_vss_daemon}.c
sed -i~ '/#include <linux.hyperv.h>/d' %{hv_fcopy_daemon}.c
gcc \
$RPM_OPT_FLAGS \
-Wno-unused-variable \
-Wno-pointer-sign \
-D_GNU_SOURCE \
-g \
%{hv_kvp_daemon}.c \
-include %{hv_kvp_daemon}.h \
-DCN_KVP_IDX=0x9 \
-DCN_KVP_VAL=0x1 \
-DKVP_SCRIPTS_PATH= \
-pthread \
-o %{hv_kvp_daemon}
gcc \
$RPM_OPT_FLAGS \
-Wno-unused-variable \
-Wno-pointer-sign \
-D_GNU_SOURCE \
-g \
%{hv_vss_daemon}.c \
-include %{hv_kvp_daemon}.h \
-DCN_VSS_IDX=0xa \
-DCN_VSS_VAL=0x1 \
-o %{hv_vss_daemon}
gcc \
$RPM_OPT_FLAGS \
-Wno-unused-variable \
-Wno-pointer-sign \
-D_GNU_SOURCE \
-g \
%{hv_fcopy_daemon}.c \
-include %{hv_kvp_daemon}.h \
-o %{hv_fcopy_daemon}
%install
# It is not a callable app anyway, so move it out of the way
bindir=%{helper_dir}/bin
mkdir -p $RPM_BUILD_ROOT${bindir}
mkdir -p $RPM_BUILD_ROOT%{_sbindir}
mkdir -p $RPM_BUILD_ROOT%{helper_dir}/bin
install -m755 %{hv_kvp_daemon} $RPM_BUILD_ROOT${bindir}
install -m755 %{hv_vss_daemon} $RPM_BUILD_ROOT${bindir}
install -m755 %{hv_fcopy_daemon} $RPM_BUILD_ROOT${bindir}
sed '
1 {
%if 0%{?suse_version} > 1315
s@^.*@#!%{_bindir}/python3@
%else
s@^.*@#!%{_bindir}/python2@
%endif
}
' %{S:0} > $RPM_BUILD_ROOT%{_sbindir}/lsvmbus
chmod 0755 $RPM_BUILD_ROOT%{_sbindir}/lsvmbus
cp -avL %{S:20} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dhcp_info
cp -avL %{S:21} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_get_dns_info
cp -avL %{S:22} $RPM_BUILD_ROOT%{helper_dir}/bin/hv_set_ifconfig
chmod 755 $RPM_BUILD_ROOT%{helper_dir}/bin/*
d=$RPM_BUILD_ROOT%{_unitdir}
mkdir -vp ${d}
#
tee ${d}/%{hv_kvp_daemon}.service <<EOF
# started via %{_udevrulesdir}/%{hv_kvp_daemon}.rules
[Unit]
Description=Hyper-V KVP Daemon
After=local-fs.target
ConditionVirtualization=microsoft
[Service]
Environment="PATH=%{helper_dir}/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=${bindir}/%{hv_kvp_daemon} --no-daemon
Restart=on-failure
[Install]
WantedBy=default.target
EOF
#
tee ${d}/%{hv_vss_daemon}.service <<EOF
# started via %{_udevrulesdir}/%{hv_vss_daemon}.rules
[Unit]
Description=Hyper-V VSS Daemon
ConditionVirtualization=microsoft
[Service]
ExecStart=${bindir}/%{hv_vss_daemon} --no-daemon
Restart=on-failure
[Install]
WantedBy=default.target
EOF
#
tee ${d}/%{hv_fcopy_daemon}.service <<EOF
# started via %{_udevrulesdir}/%{hv_fcopy_daemon}.rules
[Unit]
Description=Hyper-V host to guest file copy daemon
ConditionVirtualization=microsoft
[Service]
ExecStart=${bindir}/%{hv_fcopy_daemon} --no-daemon
Restart=on-failure
[Install]
WantedBy=default.target
EOF
#
#
#
d=$RPM_BUILD_ROOT%{_udevrulesdir}
mkdir -vp ${d}
tee ${d}/%{hv_kvp_daemon}.rules <<EOF
ACTION=="add", KERNEL=="vmbus/hv_kvp", TAG+="systemd", ENV{SYSTEMD_WANTS}+="%{hv_kvp_daemon}.service"
EOF
tee ${d}/%{hv_vss_daemon}.rules <<EOF
ACTION=="add", KERNEL=="vmbus/hv_vss", TAG+="systemd", ENV{SYSTEMD_WANTS}+="%{hv_vss_daemon}.service"
EOF
tee ${d}/%{hv_fcopy_daemon}.rules <<EOF
ACTION=="add", KERNEL=="vmbus/hv_fcopy", TAG+="systemd", ENV{SYSTEMD_WANTS}+="%{hv_fcopy_daemon}.service"
EOF
#
#
helper=inst_sys.sh
tee $RPM_BUILD_ROOT${bindir}/${helper} <<EOF
#!/bin/bash
# Starting daemons via RUN== in udev rules is not supported.
# In inst-sys systemd is not used, so start all daemons manually.
if test -d /sys/bus/vmbus/devices
then
export PATH=${bindir}:\$PATH
echo -n "Starting hyper-v helpers:"
for i in \
%{hv_kvp_daemon} \
%{hv_vss_daemon} \
%{hv_fcopy_daemon}
do
if mkdir /run/\$i
then
echo -n " \$i"
\$i < /dev/null &
fi
done
echo " ... done"
fi
EOF
chmod 755 $RPM_BUILD_ROOT${bindir}/${helper}
#
%files
%doc kvptest.ps1.txt
%{_unitdir}
%dir /usr/lib/udev
%{_udevrulesdir}
%{_sbindir}/*
%{helper_dir}
%pre
# hv_kvp_daemon in SLES11 SP2 stored temporary state files in /var/opt
# move them to /var/lib and remove old directory, if possible.
if test -d /var/opt/hyperv
then
if mkdir -p -v -m 0755 /var/lib/hyperv
then
cd /var/lib/hyperv
for oldfile in /var/opt/hyperv/ifcfg-* /var/opt/hyperv/.kvp_pool_*
do
if test -e "${oldfile}"
then
mv -vfb "${oldfile}" . || :
fi
done
cd - >/dev/null
fi
rmdir -v /var/opt/hyperv || :
fi
: nothing to do in case of systemd
%post
board_vendor=
product_name=
if cd /sys/class/dmi/id 2>/dev/null
then
if test -r board_vendor
then
board_vendor="`cat board_vendor`"
fi
if test -r product_name
then
product_name="`cat product_name`"
fi
cd - >/dev/null
fi
if test "${board_vendor}" = "Microsoft Corporation" -a "${product_name}" = "Virtual Machine"
then
: nothing to do in case of systemd
fi
%preun
: nothing to do in case of systemd
%postun
# no restart on update because the daemon can not be restarted
: nothing to do in case of systemd
%changelog

View File

@ -0,0 +1,266 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* An implementation of host to guest copy functionality for Linux.
*
* Copyright (C) 2014, Microsoft, Inc.
*
* Author : K. Y. Srinivasan <kys@microsoft.com>
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <linux/hyperv.h>
#include <linux/limits.h>
#include <syslog.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
static int target_fd;
static char target_fname[PATH_MAX];
static unsigned long long filesize;
static int hv_start_fcopy(struct hv_start_fcopy *smsg)
{
int error = HV_E_FAIL;
char *q, *p;
filesize = 0;
p = (char *)smsg->path_name;
snprintf(target_fname, sizeof(target_fname), "%s/%s",
(char *)smsg->path_name, (char *)smsg->file_name);
syslog(LOG_INFO, "Target file name: %s", target_fname);
/*
* Check to see if the path is already in place; if not,
* create if required.
*/
while ((q = strchr(p, '/')) != NULL) {
if (q == p) {
p++;
continue;
}
*q = '\0';
if (access((char *)smsg->path_name, F_OK)) {
if (smsg->copy_flags & CREATE_PATH) {
if (mkdir((char *)smsg->path_name, 0755)) {
syslog(LOG_ERR, "Failed to create %s",
(char *)smsg->path_name);
goto done;
}
} else {
syslog(LOG_ERR, "Invalid path: %s",
(char *)smsg->path_name);
goto done;
}
}
p = q + 1;
*q = '/';
}
if (!access(target_fname, F_OK)) {
syslog(LOG_INFO, "File: %s exists", target_fname);
if (!(smsg->copy_flags & OVER_WRITE)) {
error = HV_ERROR_ALREADY_EXISTS;
goto done;
}
}
target_fd = open(target_fname,
O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0744);
if (target_fd == -1) {
syslog(LOG_INFO, "Open Failed: %s", strerror(errno));
goto done;
}
error = 0;
done:
if (error)
target_fname[0] = '\0';
return error;
}
static int hv_copy_data(struct hv_do_fcopy *cpmsg)
{
ssize_t bytes_written;
int ret = 0;
bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size,
cpmsg->offset);
filesize += cpmsg->size;
if (bytes_written != cpmsg->size) {
switch (errno) {
case ENOSPC:
ret = HV_ERROR_DISK_FULL;
break;
default:
ret = HV_E_FAIL;
break;
}
syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)",
filesize, (long)bytes_written, strerror(errno));
}
return ret;
}
/*
* Reset target_fname to "" in the two below functions for hibernation: if
* the fcopy operation is aborted by hibernation, the daemon should remove the
* partially-copied file; to achieve this, the hv_utils driver always fakes a
* CANCEL_FCOPY message upon suspend, and later when the VM resumes back,
* the daemon calls hv_copy_cancel() to remove the file; if a file is copied
* successfully before suspend, hv_copy_finished() must reset target_fname to
* avoid that the file can be incorrectly removed upon resume, since the faked
* CANCEL_FCOPY message is spurious in this case.
*/
static int hv_copy_finished(void)
{
close(target_fd);
target_fname[0] = '\0';
return 0;
}
static int hv_copy_cancel(void)
{
close(target_fd);
if (strlen(target_fname) > 0) {
unlink(target_fname);
target_fname[0] = '\0';
}
return 0;
}
void print_usage(char *argv[])
{
fprintf(stderr, "Usage: %s [options]\n"
"Options are:\n"
" -n, --no-daemon stay in foreground, don't daemonize\n"
" -h, --help print this help\n", argv[0]);
}
int main(int argc, char *argv[])
{
int fcopy_fd = -1;
int error;
int daemonize = 1, long_index = 0, opt;
int version = FCOPY_CURRENT_VERSION;
union {
struct hv_fcopy_hdr hdr;
struct hv_start_fcopy start;
struct hv_do_fcopy copy;
__u32 kernel_modver;
} buffer = { };
int in_handshake;
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"no-daemon", no_argument, 0, 'n' },
{0, 0, 0, 0 }
};
while ((opt = getopt_long(argc, argv, "hn", long_options,
&long_index)) != -1) {
switch (opt) {
case 'n':
daemonize = 0;
break;
case 'h':
default:
print_usage(argv);
exit(EXIT_FAILURE);
}
}
if (daemonize && daemon(1, 0)) {
syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
exit(EXIT_FAILURE);
}
openlog("HV_FCOPY", 0, LOG_USER);
syslog(LOG_INFO, "starting; pid is:%d", getpid());
reopen_fcopy_fd:
if (fcopy_fd != -1)
close(fcopy_fd);
/* Remove any possible partially-copied file on error */
hv_copy_cancel();
in_handshake = 1;
fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR);
if (fcopy_fd < 0) {
syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s",
errno, strerror(errno));
exit(EXIT_FAILURE);
}
/*
* Register with the kernel.
*/
if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) {
syslog(LOG_ERR, "Registration failed: %s", strerror(errno));
exit(EXIT_FAILURE);
}
while (1) {
/*
* In this loop we process fcopy messages after the
* handshake is complete.
*/
ssize_t len;
len = pread(fcopy_fd, &buffer, sizeof(buffer), 0);
if (len < 0) {
syslog(LOG_ERR, "pread failed: %s", strerror(errno));
goto reopen_fcopy_fd;
}
if (in_handshake) {
if (len != sizeof(buffer.kernel_modver)) {
syslog(LOG_ERR, "invalid version negotiation");
exit(EXIT_FAILURE);
}
in_handshake = 0;
syslog(LOG_INFO, "kernel module version: %u",
buffer.kernel_modver);
continue;
}
switch (buffer.hdr.operation) {
case START_FILE_COPY:
error = hv_start_fcopy(&buffer.start);
break;
case WRITE_TO_FILE:
error = hv_copy_data(&buffer.copy);
break;
case COMPLETE_FCOPY:
error = hv_copy_finished();
break;
case CANCEL_FCOPY:
error = hv_copy_cancel();
break;
default:
error = HV_E_FAIL;
syslog(LOG_ERR, "Unknown operation: %d",
buffer.hdr.operation);
}
/*
* pwrite() may return an error due to the faked CANCEL_FCOPY
* message upon hibernation. Ignore the error by resetting the
* dev file, i.e. closing and re-opening it.
*/
if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) {
syslog(LOG_ERR, "pwrite failed: %s", strerror(errno));
goto reopen_fcopy_fd;
}
}
}

View File

@ -0,0 +1,28 @@
#!/bin/bash
# This script retrieves the DHCP state of a given interface.
# In the interest of keeping the KVP daemon code free of distro specific
# information; the kvp daemon code invokes this external script to gather
# DHCP setting for the specific interface.
#
# Input: Name of the interface
#
# Output: The script prints the string "Enabled" to stdout to indicate
# that DHCP is enabled on the interface. If DHCP is not enabled,
# the script prints the string "Disabled" to stdout.
#
# Each Distro is expected to implement this script in a distro specific
# fashion. For instance, on Distros that ship with Network Manager enabled,
# this script can be based on the Network Manager APIs for retrieving DHCP
# information.
if_file="/etc/sysconfig/network/ifcfg-$1"
dhcp=$(grep -- '^BOOTPROTO=.*dhcp' "$if_file" 2>/dev/null)
if [ "$dhcp" != "" ];
then
echo "Enabled"
else
echo "Disabled"
fi

View File

@ -0,0 +1,16 @@
#!/bin/bash
# This script parses /etc/resolv.conf to retrive DNS information.
# In the interest of keeping the KVP daemon code free of distro specific
# information; the kvp daemon code invokes this external script to gather
# DNS information.
# This script is expected to print the nameserver values to stdout.
# Each Distro is expected to implement this script in a distro specific
# fashion. For instance on Distros that ship with Network Manager enabled,
# this script can be based on the Network Manager APIs for retrieving DNS
# entries.
if test -r /etc/resolv.conf
then
awk -- '/^nameserver/ { print $2 }' /etc/resolv.conf
fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
#!/bin/bash
#
# In the interest of keeping the KVP daemon code free of distro specific
# information; the kvp daemon code invokes this external script to configure
# the interface.
#
# The only argument to this script is the configuration file that is to
# be used to configure the interface.
#
# Here is the format of the ip configuration file:
#
# HWADDR=macaddr
# DEVICE=interface name
# BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
# or "none" if no boot-time protocol should be used)
#
# IPADDR0=ipaddr1
# IPADDR1=ipaddr2
# IPADDRx=ipaddry (where y = x + 1)
#
# NETMASK0=netmask1
# NETMASKx=netmasky (where y = x + 1)
#
# GATEWAY=ipaddr1
# GATEWAYx=ipaddry (where y = x + 1)
#
# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc)
#
# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be
# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
# IPV6NETMASK.
#
# The host can specify multiple ipv4 and ipv6 addresses to be
# configured for the interface. Furthermore, the configuration
# needs to be persistent. A subsequent GET call on the interface
# is expected to return the configuration that is set via the SET
# call.
#
cfg=$1
if ! test -f "${cfg}"
then
: expect configuration datafile as first argument
exit 1
fi
# send subshell output to syslog
(
# copied from /etc/sysconfig/network/scripts/functions
mask2pfxlen() {
local i octet width=0 mask=(${1//./ })
test ${#mask[@]} -eq 4 || return 1
for octet in 0 1 2 3
do
test "${mask[octet]}" -ge 0 -a "${mask[octet]}" -le 255 || return 1
for i in 128 192 224 240 248 252 254 255
do
test ${mask[octet]} -ge $i && ((width++))
done
done
echo $width
return 0
}
pfxlen2mask() {
test -n "$1" || return 1
local o i n=0 adr=() len=$(($1))
for o in 0 1 2 3
do
adr[$o]=0
for i in 128 64 32 16 8 4 2 1
do
((n++ < len)) && ((adr[$o] = ${adr[$o]} + $i))
done
done
echo ${adr[0]}.${adr[1]}.${adr[2]}.${adr[3]}
return 0
}
# remove known config variables from environment
unset HWADDR
unset BOOTPROTO
unset DEVICE
unset ${!IPADDR*}
unset ${!NETMASK*}
unset ${!GATEWAY*}
unset ${!IPV6ADDR*}
unset ${!IPV6NETMASK*}
unset ${!IPV6_DEFAULTGW*}
unset ${!DNS*}
. "$1"
#
if test -z "${DEVICE}"
then
echo "Missing DEVICE= in ${cfg}"
exit 1
fi
#
t_ifcfg=`mktemp`
t_ifroute=`mktemp`
_exit() {
rm -f "${t_ifcfg}" "${t_ifroute}"
}
trap _exit EXIT
#
if test -z "${t_ifcfg}" || test -z "${t_ifroute}"
then
exit 1
fi
#
# Create ifcfg-* file
(
echo "STARTMODE=auto"
#
if test -n "${HWADDR}"
then
: # ignore HWADDR, it just repeats the existing MAC value
fi
#
if test "${BOOTPROTO}" = "dhcp"
then
echo "BOOTPROTO=dhcp"
elif test -n "${!IPADDR*}${!IPV6ADDR*}"
then
echo "BOOTPROTO=static"
fi
# single index for all ipv4 and ipv6 adresses in final ifcfg file
i=0
idx=""
# loop through all ipv4 adresses
for var in ${!IPADDR*}
do
index=${var#IPADDR}
pfx=
# find corresponding NETMASK variable
eval nm=\$NETMASK${index}
# if specified, calculate prefix
if test -n "${nm}"
then
pfx=`mask2pfxlen "${nm}" 2>/dev/null`
fi
# if not specified, force prefix
if test -z "${pfx}"
then
pfx="32"
fi
# construct actual value
eval val=\$IPADDR${index}
# write config variable
echo "IPADDR${idx}='${val}/${pfx}'"
idx="_$((++i))"
done
# loop through all ipv6 adresses
for var in ${!IPV6ADDR*}
do
index=${var#IPV6ADDR}
# find corresponding IPV6NETMASK variable
eval pfx=\$IPV6NETMASK${index}
# if not specified, force prefix
if test -z "${pfx}"
then
pfx=128
fi
# construct actual value
eval val=\$IPV6ADDR${index}
# write config variable
echo "IPADDR${idx}='${val}/${pfx}'"
idx="_$((++i))"
done
) >> "${t_ifcfg}"
# Create ifroute-* file
(
if test -n "${GATEWAY}"
then
echo "default $GATEWAY - $DEVICE"
fi
if test -n "${IPV6_DEFAULTGW}"
then
echo "default $IPV6_DEFAULTGW - $DEVICE"
fi
) >> "${t_ifroute}"
# Only a single default gateway is supported
unset GATEWAY IPV6_DEFAULTGW
if test -n "${!GATEWAY*}${!IPV6_DEFAULTGW*}"
then
echo "WARNING: multiple gateways not supported: ${!GATEWAY*} ${!IPV6_DEFAULTGW*}"
fi
# collect DNS info
_DNS_=
for var in ${!DNS*}
do
eval val=\$${var}
if test -n "${_DNS_}"
then
_DNS_="${_DNS_} ${val}"
else
_DNS_=${val}
fi
done
#
echo "$0: working on network interface ifcfg-${DEVICE}"
cp -fb ${t_ifcfg} "/etc/sysconfig/network/ifcfg-${DEVICE}"
cp -fb ${t_ifroute} "/etc/sysconfig/network/ifroute-${DEVICE}"
if test -w /etc/sysconfig/network/config
then
sed -i "s@^NETCONFIG_DNS_STATIC_SERVERS=.*@NETCONFIG_DNS_STATIC_SERVERS='$_DNS_'@" /etc/sysconfig/network/config
netconfig update -m dns
fi
ifdown "${DEVICE}"
ifup "${DEVICE}"
) 2>&1 | logger -t "${0##*/}[$PPID / $$]"

View File

@ -0,0 +1,355 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* An implementation of the host initiated guest snapshot for Hyper-V.
*
* Copyright (C) 2013, Microsoft, Inc.
* Author : K. Y. Srinivasan <kys@microsoft.com>
*/
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <stdio.h>
#include <mntent.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/hyperv.h>
#include <syslog.h>
#include <getopt.h>
#include <stdbool.h>
#include <dirent.h>
static bool fs_frozen;
/* Don't use syslog() in the function since that can cause write to disk */
static int vss_do_freeze(char *dir, unsigned int cmd)
{
int ret, fd = open(dir, O_RDONLY);
if (fd < 0)
return 1;
ret = ioctl(fd, cmd, 0);
/*
* If a partition is mounted more than once, only the first
* FREEZE/THAW can succeed and the later ones will get
* EBUSY/EINVAL respectively: there could be 2 cases:
* 1) a user may mount the same partition to different directories
* by mistake or on purpose;
* 2) The subvolume of btrfs appears to have the same partition
* mounted more than once.
*/
if (ret) {
if ((cmd == FIFREEZE && errno == EBUSY) ||
(cmd == FITHAW && errno == EINVAL)) {
close(fd);
return 0;
}
}
close(fd);
return !!ret;
}
static bool is_dev_loop(const char *blkname)
{
char *buffer;
DIR *dir;
struct dirent *entry;
bool ret = false;
buffer = malloc(PATH_MAX);
if (!buffer) {
syslog(LOG_ERR, "Can't allocate memory!");
exit(1);
}
snprintf(buffer, PATH_MAX, "%s/loop", blkname);
if (!access(buffer, R_OK | X_OK)) {
ret = true;
goto free_buffer;
} else if (errno != ENOENT) {
syslog(LOG_ERR, "Can't access: %s; error:%d %s!",
buffer, errno, strerror(errno));
}
snprintf(buffer, PATH_MAX, "%s/slaves", blkname);
dir = opendir(buffer);
if (!dir) {
if (errno != ENOENT)
syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!",
buffer, errno, strerror(errno));
goto free_buffer;
}
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname,
entry->d_name);
if (is_dev_loop(buffer)) {
ret = true;
break;
}
}
closedir(dir);
free_buffer:
free(buffer);
return ret;
}
static int vss_operate(int operation)
{
char match[] = "/dev/";
FILE *mounts;
struct mntent *ent;
struct stat sb;
char errdir[1024] = {0};
char blkdir[23]; /* /sys/dev/block/XXX:XXX */
unsigned int cmd;
int error = 0, root_seen = 0, save_errno = 0;
switch (operation) {
case VSS_OP_FREEZE:
cmd = FIFREEZE;
break;
case VSS_OP_THAW:
cmd = FITHAW;
break;
default:
return -1;
}
mounts = setmntent("/proc/mounts", "r");
if (mounts == NULL)
return -1;
while ((ent = getmntent(mounts))) {
if (strncmp(ent->mnt_fsname, match, strlen(match)))
continue;
if (stat(ent->mnt_fsname, &sb)) {
syslog(LOG_ERR, "Can't stat: %s; error:%d %s!",
ent->mnt_fsname, errno, strerror(errno));
} else {
sprintf(blkdir, "/sys/dev/block/%d:%d",
major(sb.st_rdev), minor(sb.st_rdev));
if (is_dev_loop(blkdir))
continue;
}
if (hasmntopt(ent, MNTOPT_RO) != NULL)
continue;
if (strcmp(ent->mnt_type, "vfat") == 0)
continue;
if (strcmp(ent->mnt_dir, "/") == 0) {
root_seen = 1;
continue;
}
error |= vss_do_freeze(ent->mnt_dir, cmd);
if (operation == VSS_OP_FREEZE) {
if (error)
goto err;
fs_frozen = true;
}
}
endmntent(mounts);
if (root_seen) {
error |= vss_do_freeze("/", cmd);
if (operation == VSS_OP_FREEZE) {
if (error)
goto err;
fs_frozen = true;
}
}
if (operation == VSS_OP_THAW && !error)
fs_frozen = false;
goto out;
err:
save_errno = errno;
if (ent) {
strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
endmntent(mounts);
}
vss_operate(VSS_OP_THAW);
fs_frozen = false;
/* Call syslog after we thaw all filesystems */
if (ent)
syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
errdir, save_errno, strerror(save_errno));
else
syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
strerror(save_errno));
out:
return error;
}
void print_usage(char *argv[])
{
fprintf(stderr, "Usage: %s [options]\n"
"Options are:\n"
" -n, --no-daemon stay in foreground, don't daemonize\n"
" -h, --help print this help\n", argv[0]);
}
int main(int argc, char *argv[])
{
int vss_fd = -1, len;
int error;
struct pollfd pfd;
int op;
struct hv_vss_msg vss_msg[1];
int daemonize = 1, long_index = 0, opt;
int in_handshake;
__u32 kernel_modver;
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"no-daemon", no_argument, 0, 'n' },
{0, 0, 0, 0 }
};
while ((opt = getopt_long(argc, argv, "hn", long_options,
&long_index)) != -1) {
switch (opt) {
case 'n':
daemonize = 0;
break;
case 'h':
print_usage(argv);
exit(0);
default:
print_usage(argv);
exit(EXIT_FAILURE);
}
}
if (daemonize && daemon(1, 0))
return 1;
openlog("Hyper-V VSS", 0, LOG_USER);
syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
reopen_vss_fd:
if (vss_fd != -1)
close(vss_fd);
if (fs_frozen) {
if (vss_operate(VSS_OP_THAW) || fs_frozen) {
syslog(LOG_ERR, "failed to thaw file system: err=%d",
errno);
exit(EXIT_FAILURE);
}
}
in_handshake = 1;
vss_fd = open("/dev/vmbus/hv_vss", O_RDWR);
if (vss_fd < 0) {
syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s",
errno, strerror(errno));
exit(EXIT_FAILURE);
}
/*
* Register ourselves with the kernel.
*/
vss_msg->vss_hdr.operation = VSS_OP_REGISTER1;
len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
if (len < 0) {
syslog(LOG_ERR, "registration to kernel failed; error: %d %s",
errno, strerror(errno));
close(vss_fd);
exit(EXIT_FAILURE);
}
pfd.fd = vss_fd;
while (1) {
pfd.events = POLLIN;
pfd.revents = 0;
if (poll(&pfd, 1, -1) < 0) {
syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno));
if (errno == EINVAL) {
close(vss_fd);
exit(EXIT_FAILURE);
}
else
continue;
}
len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
if (in_handshake) {
if (len != sizeof(kernel_modver)) {
syslog(LOG_ERR, "invalid version negotiation");
exit(EXIT_FAILURE);
}
kernel_modver = *(__u32 *)vss_msg;
in_handshake = 0;
syslog(LOG_INFO, "VSS: kernel module version: %d",
kernel_modver);
continue;
}
if (len != sizeof(struct hv_vss_msg)) {
syslog(LOG_ERR, "read failed; error:%d %s",
errno, strerror(errno));
goto reopen_vss_fd;
}
op = vss_msg->vss_hdr.operation;
error = HV_S_OK;
switch (op) {
case VSS_OP_FREEZE:
case VSS_OP_THAW:
error = vss_operate(op);
syslog(LOG_INFO, "VSS: op=%s: %s\n",
op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
error ? "failed" : "succeeded");
if (error) {
error = HV_E_FAIL;
syslog(LOG_ERR, "op=%d failed!", op);
syslog(LOG_ERR, "report it with these files:");
syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
}
break;
case VSS_OP_HOT_BACKUP:
syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP\n");
break;
default:
syslog(LOG_ERR, "Illegal op:%d\n", op);
}
/*
* The write() may return an error due to the faked VSS_OP_THAW
* message upon hibernation. Ignore the error by resetting the
* dev file, i.e. closing and re-opening it.
*/
vss_msg->error = error;
len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
if (len != sizeof(struct hv_vss_msg)) {
syslog(LOG_ERR, "write failed; error: %d %s", errno,
strerror(errno));
goto reopen_vss_fd;
}
}
close(vss_fd);
exit(0);
}