[virt-who] spec: create /var dir in the spec instead of source
by Radek Novacek
commit 67394306e7e613464a05e0ea55da2807d1b300ee
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Aug 26 10:28:25 2013 +0200
spec: create /var dir in the spec instead of source
Also install virt-who-register-satellite
satellite.py | 2 --
virt-who.spec | 3 +++
2 files changed, 3 insertions(+), 2 deletions(-)
---
diff --git a/satellite.py b/satellite.py
index 14433d4..e25ae15 100644
--- a/satellite.py
+++ b/satellite.py
@@ -92,8 +92,6 @@ class Satellite(object):
self.logger.exception("Unable to refresh HW profile")
raise SatelliteError("Unable to refresh HW profile: %s" % str(e))
try:
- if not os.path.isdir(self.VAR_DIR):
- os.mkdir(self.VAR_DIR, 0600)
f = open(self.HYPERVISOR_SYSTEMID_FILE, "w")
try:
pickle.dump(new_system, f)
diff --git a/virt-who.spec b/virt-who.spec
index 75ea8f7..cd37072 100644
--- a/virt-who.spec
+++ b/virt-who.spec
@@ -37,6 +37,7 @@ report them to the subscription manager.
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
+mkdir -p %{buildroot}/%{_sharedstatedir}/%{name}
# Don't run test suite in check section, because it need the system to be
# registered to subscription-manager server
@@ -63,10 +64,12 @@ fi
%files
%doc README LICENSE
%{_bindir}/virt-who
+%{_bindir}/virt-who-register-satellite
%{_datadir}/virt-who/
%{_sysconfdir}/rc.d/init.d/virt-who
%config(noreplace) %{_sysconfdir}/sysconfig/virt-who
%{_mandir}/man8/virt-who.8.gz
+%{_sharedstatedir}/%{name}
%changelog
10 years, 9 months
[virt-who] Handle exceptions in virt_notify function
by Radek Novacek
commit 5c1b00697c5e7ce2dfbc08881f1cf112664b2502
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Aug 26 10:20:35 2013 +0200
Handle exceptions in virt_notify function
satellite.py | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
---
diff --git a/satellite.py b/satellite.py
index 0e42d70..14433d4 100644
--- a/satellite.py
+++ b/satellite.py
@@ -157,7 +157,11 @@ class Satellite(object):
plan = self._assemble_plan(uuids)
self.logger.debug("Sending plan: %s" % plan)
# Send the mapping
- res = self.server.registration.virt_notify(self.systemid, plan)
+ try:
+ res = self.server.registration.virt_notify(self.systemid, plan)
+ except Exception, e:
+ self.logger.exception("Unable to send host/guest assocaition to the satellite:")
+ raise SatelliteError("Unable to send host/guest assocaition to the satellite: % " % str(e))
# TODO: figure out what to populate here
result = {}
10 years, 9 months
[virt-who] Fix syntax for python 2.4
by Radek Novacek
commit bb464081e772e7f7db24362c623d24695f4a59ed
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Aug 26 10:20:14 2013 +0200
Fix syntax for python 2.4
satellite.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
---
diff --git a/satellite.py b/satellite.py
index b541994..0e42d70 100644
--- a/satellite.py
+++ b/satellite.py
@@ -70,8 +70,8 @@ class Satellite(object):
def _register_hypervisor(self, username, password, options):
if options is None:
- # We need to emulate options object form argparse
- class O(): pass
+ # We need to emulate options object from argparse
+ class O(object): pass
options = O()
# Fill in some defaults
if not hasattr(options, "profile_name") or options.profile_name is None:
10 years, 9 months
[virt-who] Add satellite support
by Radek Novacek
commit 6f94928d31de6570cf88f8a0d48cb8b1a480b087
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Thu Aug 22 16:08:17 2013 +0200
Add satellite support
Support also satellite as subscription manager (for hypervisor mode
only).
Makefile | 1 +
README | 26 ++++---
satellite.py | 197 +++++++++++++++++++++++++++++++++++++++++++
virt-who-register-satellite | 10 ++
virt-who.8 | 52 +++++++++++-
virt-who.conf | 13 +++
virt-who.py | 68 ++++++++++++---
7 files changed, 341 insertions(+), 26 deletions(-)
---
diff --git a/Makefile b/Makefile
index 6dee540..5331a4a 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ install:
install -d $(DESTDIR)/usr/share/$(name)/ $(DESTDIR)/usr/bin $(DESTDIR)/etc/rc.d/init.d $(DESTDIR)/etc/sysconfig $(DESTDIR)/usr/share/man/man8/
install -pm 0644 *.py $(DESTDIR)/usr/share/$(name)/
install virt-who $(DESTDIR)/usr/bin/
+ install virt-who-register-satellite $(DESTDIR)/usr/bin/
install virt-who-initscript $(DESTDIR)/etc/rc.d/init.d/virt-who
install -pm 0644 virt-who.conf $(DESTDIR)/etc/sysconfig/virt-who
gzip -c virt-who.8 > virt-who.8.gz
diff --git a/README b/README
index 0c793d8..c9cb029 100644
--- a/README
+++ b/README
@@ -1,9 +1,9 @@
-virt-who is agent for reporting virtual guest IDs to subscription-manager.
+virt-who is agent for reporting virtual guest IDs to subscription manager
+(SAM or Satellite).
-It uses libvirt-python to obtain UUIDs of all virtual guests present
-in the system (both running and stopped). It then connects to
-subscription-manager server (candlepin) and set the list of UUIDs to facts
-about host system.
+It works either locally or via remote hypervisor. It obtains list of UUIDs
+on specified hypervisor (or local system) and then it sends the list of UUIDs
+(or host/guest association to the subscription manager (SAM, Satellite).
Installation
@@ -19,16 +19,20 @@ $ make rpm
and then install the package
+
Configuration
-------------
-It uses rhsm configuration (usually in /etc/rhsm/rhsm.conf). The system needs
-to be registered in subscription-manager server before running the agent.
+SAM:
+ It uses rhsm configuration (usually in /etc/rhsm/rhsm.conf). The system
+ needs to be registered in subscription-manager server before running
+ the agent.
+Satellite:
+ Configuration is stored in virt-who configuration file:
+ /etc/sysconfig/virt-who
+
Usage
-----
-This agent has two modes of running. First [default] is to obtain UUIDs, send
-them to the server and exit. Second mode is running in infinite loop and
-monitor guests UUIDs changes. When some change happens it will be immediately
-send.
+See the manual page
diff --git a/satellite.py b/satellite.py
new file mode 100644
index 0000000..b541994
--- /dev/null
+++ b/satellite.py
@@ -0,0 +1,197 @@
+"""
+Module for communcating with Satellite (RHN Classic), part of virt-who
+
+Copyright (C) 2013 Radek Novacek <rnovacek(a)redhat.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+"""
+
+import sys
+import os
+import xmlrpclib
+import pickle
+
+class SatelliteError(Exception):
+ def __init__(self, message):
+ self.message = message
+
+ def __str__(self):
+ return self.message
+
+class Satellite(object):
+ """ Class for interacting with satellite (RHN Classic). """
+ VAR_DIR = "/var/lib/virt-who/"
+ HYPERVISOR_SYSTEMID_FILE = VAR_DIR + "hypervisor-systemid"
+ def __init__(self, logger):
+ self.logger = logger
+ self.server = None
+
+ def connect(self, server, username, password, options=None, force_register=False):
+ # initialize a new system if one doesn't already exist
+ if not server.startswith("http://") and not server.startswith("https://"):
+ server = "https://%s" % server
+ if not server.endswith("XMLRPC"):
+ server = "%s/XMLRPC" % server
+
+ self.logger.debug("Initializing satellite connection to %s" % server)
+ try:
+ self.server = xmlrpclib.Server(server, verbose=0)
+ except Exception:
+ self.logger.exception("Unable to connect to the Satellite server")
+ raise SatelliteError("Unable to connect to the Satellite server")
+ self.logger.info("Initialized satellite connection")
+
+ # initialize a new system if one doesn't already exist
+ if force_register:
+ new_system = self._register_hypervisor(username, password, options)
+ else:
+ try:
+ self.logger.debug("Loading system id info from %s" % self.HYPERVISOR_SYSTEMID_FILE)
+ new_system = pickle.load(open(self.HYPERVISOR_SYSTEMID_FILE, "rb"))
+ except IOError:
+ new_system = self._register_hypervisor(username, password, options)
+
+ if new_system is None:
+ raise SatelliteError("Unable to register hypervisor")
+
+ self.systemid = new_system["system_id"]
+
+ def _register_hypervisor(self, username, password, options):
+ if options is None:
+ # We need to emulate options object form argparse
+ class O(): pass
+ options = O()
+ # Fill in some defaults
+ if not hasattr(options, "profile_name") or options.profile_name is None:
+ options.profile_name = "hypervisor"
+ if not hasattr(options, "os_release_name") or options.os_release_name is None:
+ options.os_release_name = "unknown"
+ if not hasattr(options, "version") or options.version is None:
+ # TODO: what to do here? 6Server will consume subscription
+ options.version = "6Server"
+ if not hasattr(options, "arch") or options.arch is None:
+ options.arch = "x86_64"
+
+ try:
+ new_system = self.server.registration.new_system_user_pass(options.profile_name,
+ options.os_release_name, options.version, options.arch, username, password, {})
+ self.server.registration.refresh_hw_profile(new_system['system_id'], [])
+ except Exception, e:
+ self.logger.exception("Unable to refresh HW profile")
+ raise SatelliteError("Unable to refresh HW profile: %s" % str(e))
+ try:
+ if not os.path.isdir(self.VAR_DIR):
+ os.mkdir(self.VAR_DIR, 0600)
+ f = open(self.HYPERVISOR_SYSTEMID_FILE, "w")
+ try:
+ pickle.dump(new_system, f)
+ finally:
+ f.close()
+ except (OSError, IOError), e:
+ self.logger.error("Unable to write system id to %s: %s" % (self.HYPERVISOR_SYSTEMID_FILE, str(e)))
+
+ self.logger.debug("New system created in satellite, system id saved in %s" % self.HYPERVISOR_SYSTEMID_FILE)
+
+ return new_system
+
+ def readConfig(self):
+ """
+ not implemented; config info is passed in via virt-who conf
+ """
+ pass
+
+ def _assemble_plan(self, uuids):
+
+ events = []
+
+ # the stub_instance_info is not used by the report. When the guest system checks in, it will provide
+ # actual hardware info
+ stub_instance_info = {
+ 'vcpus' : 1,
+ 'memory_size' : 0,
+ 'virt_type' : 'fully_virtualized',
+ 'state' : 'running',
+ # TODO: put hypervisor's hostname here maybe
+ 'name': "virtual machine from %s" % 'vmware hypervisor'
+ }
+
+ # declare the hypervisor. always use 16 zeros for the hypervisor's UUID, per rhn-virtualization-host
+ events.append([0, 'exists', 'system', {'identity': 'host', 'uuid': self.uuid()}])
+
+ events.append([0, 'crawl_began', 'system', {}])
+ for uuid in uuids:
+ stub_instance_info['uuid'] = uuid
+ events.append([0, 'exists', 'domain', stub_instance_info.copy()])
+ events.append([0, 'crawl_ended', 'system', {}])
+
+ return events
+
+ def sendVirtGuests(self, domains):
+ raise SatelliteError("virt-who does not support sending local hypervisor data to satellite; use rhn-virtualization-host instead")
+
+ def hypervisorCheckIn(self, owner, env, mapping):
+ self.logger.debug("Building plan for mapping: %s" % mapping)
+ if self.server is None:
+ return
+ uuids = []
+ for guestlist in mapping.values():
+ for uuid in guestlist:
+ # Get rid of dashes from UUID
+ uuids.append(str(uuid).replace("-", ""))
+ uuids.sort()
+
+ self.logger.debug("Sending flattened list of uuids: %s" % uuids)
+
+ plan = self._assemble_plan(uuids)
+ self.logger.debug("Sending plan: %s" % plan)
+ # Send the mapping
+ res = self.server.registration.virt_notify(self.systemid, plan)
+
+ # TODO: figure out what to populate here
+ result = {}
+ for type in ['failedUpdate', 'created', 'updated']:
+ result[type] = []
+
+ return result
+
+ def uuid(self):
+ """ Satellite expects a zeroed-out hypervisor UUID """
+ return '0000000000000000'
+
+ def getFacts(self):
+ """ Not implemented """
+ pass
+
+if __name__ == '__main__':
+ from optparse import OptionParser
+ import logging
+ parser = OptionParser(usage="virt-who-register-satellite [-n name] [-o operating_system] [-v version] [-a arch] server username password",
+ description="Register hypervisor to the satellite server")
+ parser.add_option("-n", "--name", action="store", dest="profile_name", default=None, help="Name of the hypervisor")
+ parser.add_option("-o", "--operating-system", action="store", dest="os_release_name", default=None, help="Operating system of the hypervisor")
+ parser.add_option("-v", "--version", action="store", dest="version", default=None, help="Operating system version")
+ parser.add_option("-a", "--arch", action="store", dest="arch", default=None, help="Hypervisor architecture")
+ (options, args) = parser.parse_args()
+ if len(args) < 3:
+ parser.print_usage()
+ sys.exit(1)
+
+ logger = logging.getLogger()
+ logger.addHandler(logging.StreamHandler())
+ satellite = Satellite(logger)
+ try:
+ satellite.connect(args[0], args[1], args[2], force_register=True, options=options)
+ except Exception:
+ logger.exception("Unable to connect to Satellite:")
diff --git a/virt-who-register-satellite b/virt-who-register-satellite
new file mode 100755
index 0000000..8204df9
--- /dev/null
+++ b/virt-who-register-satellite
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ -f ./satellite.py ];
+then
+ # Run it from local directory when available
+ exec /usr/bin/python ./satellite.py "$@"
+else
+ # Run it from /usr/share/virt-who
+ exec /usr/bin/python /usr/share/virt-who/satellite.py "$@"
+fi
diff --git a/virt-who.8 b/virt-who.8
index 715cce1..0a0aa9a 100644
--- a/virt-who.8
+++ b/virt-who.8
@@ -1,8 +1,8 @@
-.TH VIRT-WHO "8" "September 2012" "virt-who"
+.TH VIRT-WHO "8" "August 2013" "virt-who"
.SH NAME
virt-who - Agent for reporting virtual guest IDs to Subscription Asset Manager.
.SH SYNOPSIS
-virt-who [-d] [-i INTERVAL] [-b] [-o] [--libvirt|--vdsm|--esx|--rhevm|--hyperv]
+virt-who [-d] [-i INTERVAL] [-b] [-o] [--sam|--satellite] [--libvirt|--vdsm|--esx|--rhevm|--hyperv]
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
@@ -19,6 +19,10 @@ Send the list of guest IDs and exit immediately
.TP
\fB\-i\fR INTERVAL, \fB\-\-interval\fR=\fIINTERVAL\fR
Acquire and send list of virtual guest each N seconds
+.IP
+.SS Virtualization backend
+.IP
+Choose virtualization backend that should be used to gather host/guest associations
.TP
\fB\-\-libvirt\fR
Use libvirt to list virtual guests [default]
@@ -35,6 +39,16 @@ Register guests using RHEV\-M
\fB\-\-hyperv\fR
Register guests using Hyper\-V
.IP
+.SS Subscription manager
+.IP
+Choose where the host/guest associations should be reported
+.TP
+\fB\-\-sam\fR
+Report host/guest associations to the Subscription Asset Manager [default]
+.TP
+\fB\-\-satellite\fR
+Report host/guest associations to the Satellite
+.IP
.SS vCenter/ESX options
.IP
Use this options with \fB\-\-esx\fR
@@ -91,6 +105,19 @@ Username for connecting to Hyper\-V
.TP
\fB\-\-hyperv\-password\fR=\fIPASSWORD\fR
Password for connecting to Hyper\-V
+.IP
+.SS Satellite options:
+.IP
+Use this options with \fB\-\-satellite\fR
+.TP
+\fB\-\-satellite-server\fR=\fISAT_SERVER
+Satellite server URL
+.TP
+\fB\-\-satellite-username\fR=\fISAT_USERNAME
+Username for connecting to Satellite server
+.TP
+\fB\-\-satellite-password\fR=\fISAT_PASSWORD
+Password for connecting to Satellite server
.PP
.SH ENVIRONMENT
virt-who also reads environmental variables. They have the same name as command line arguments but upper-cased, with underscore instead of dash and prefixed with VIRTWHO_ (e.g. VIRTWHO_ONE_SHOT). Empty variables are considered as disabled, non-empty as enabled
@@ -117,7 +144,7 @@ NOTE: virt-who don't print anything to terminal in this mode
.IP
NOTE: monitoring for events requires libvirt backend, but this mode can be used with all backends.
-.SS BACKEND
+.SS VIRTUALIZATION BACKEND
virt-who can use couple of virtualization backends.
.TP
@@ -156,6 +183,25 @@ Use RHEV-M as virtualization backend and specify option required to connect to R
Use Hyper-V as virtualization backend and specify option required to connect to Hyper-V server.
+.SS SUBSCRIPTION MANAGER
+
+virt-who can report host/guest associations either to Subscription Asset Manager (SAM) or to Satellite.
+.TP
+1. Subscription Asset Manager
+# virt-who
+
+# virt-who --sam
+
+System must be registered using subscription-manager prior to using virt-who. Configuration for connecting to SAM is shared between subscription-manager and virt-who. This is default.
+
+.TP
+2. Satellite
+# virt-who --satellite --satellite-server=SAT_SERVER --satellite-username=SAT_USERNAME --satellite-password=SAT_PASSWORD
+
+# virt-who --satellite --satellite-server=SAT_SERVER
+
+This option can't be used for monitoring local guests, use rhn-virtualization-host instead. Username and password might not be specified but in that case the system must be registered beforehand using virt-who-register-satellite command.
+
.SH LOGGING
virt-who always writes error output to file /var/log/rhsm/rhsm.log. In all modes, excluding background ("-b"), it writes same output also to the standard error output.
diff --git a/virt-who.conf b/virt-who.conf
index 2c117d2..39ab978 100644
--- a/virt-who.conf
+++ b/virt-who.conf
@@ -18,6 +18,12 @@ VIRTWHO_DEBUG=0
# configuration.
#VIRTWHO_INTERVAL=0
+# virt-who subscription manager backend, enable ony one option from following 2:
+# Report to Subscription Asset Manager (SAM)
+#VIRTWHO_SAM=1
+# Report to Satellite
+#VIRTWHO_SATELLITE=0
+
# virt-who mode, enable only one option from following 5:
# Use libvirt to list virtual guests [default]
#VIRTWHO_LIBVIRT=1
@@ -50,3 +56,10 @@ VIRTWHO_DEBUG=0
#VIRTWHO_HYPERV_SERVER=
#VIRTWHO_HYPERV_USERNAME=
#VIRTWHO_HYPERV_PASSWORD=
+
+# Option for Satellite backend
+#VIRTWHO_SATELLITE_SERVER=
+# Username and password might not be specified but the system must be
+# registered using virt-who-register-satellite first.
+#VIRTWHO_SATELLITE_USERNAME=
+#VIRTWHO_SATELLITE_PASSWORD=
diff --git a/virt-who.py b/virt-who.py
index 52ec318..53051ef 100644
--- a/virt-who.py
+++ b/virt-who.py
@@ -31,6 +31,7 @@ from rhevm import RHEVM
from hyperv import HyperV
from event import virEventLoopPureStart
from subscriptionmanager import SubscriptionManager, SubscriptionManagerError
+from satellite import Satellite, SatelliteError
import logging
import log
@@ -39,9 +40,9 @@ from optparse import OptionParser, OptionGroup
class OptionParserEpilog(OptionParser):
""" Epilog is new in Python 2.5, we need to support Python 2.4. """
- def __init__(self, description, epilog=None):
+ def __init__(self, usage="%prog [options]", description=None, epilog=None):
self.myepilog = epilog
- OptionParser.__init__(self, description)
+ OptionParser.__init__(self, usage=usage, description=description)
def format_help(self, formatter=None):
if formatter is None:
@@ -110,14 +111,24 @@ class VirtWho(object):
Connect to the subscription manager (candlepin).
"""
try:
- self.subscriptionManager = SubscriptionManager(self.logger)
- self.subscriptionManager.connect()
+ if self.options.smType == "rhsm":
+ self.subscriptionManager = SubscriptionManager(self.logger)
+ self.subscriptionManager.connect()
+ elif self.options.smType == "satellite":
+ self.subscriptionManager = Satellite(self.logger)
+ self.subscriptionManager.connect(self.options.sat_server, self.options.sat_username, self.options.sat_password)
except NoOptionError, e:
self.logger.exception("Error in reading configuration file (/etc/rhsm/rhsm.conf):")
- return
+ raise
except SubscriptionManagerError, e:
self.logger.exception("Unable to obtain status from server, UEPConnection is likely not usable:")
- return
+ raise
+ except SatelliteError, e:
+ self.logger.exception("Unable to connect to the RHN Satellite:")
+ raise
+ except Exception, e:
+ self.logger.exception("Unknown error")
+ raise
if self.options.virtType == "libvirt":
self.tryRegisterEventCallback()
@@ -318,17 +329,26 @@ def main():
sys.exit(1)
createPidFile()
- parser = OptionParserEpilog(description="Agent for reporting virtual guest IDs to subscription-manager",
+ parser = OptionParserEpilog(usage="virt-who [-d] [-i INTERVAL] [-b] [-o] [--sam|--satellite] [--libvirt|--vdsm|--esx|--rhevm|--hyperv]",
+ description="Agent for reporting virtual guest IDs to subscription manager",
epilog="virt-who also reads enviromental variables. They have the same name as command line arguments but uppercased, with underscore instead of dash and prefixed with VIRTWHO_ (e.g. VIRTWHO_ONE_SHOT). Empty variables are considered as disabled, non-empty as enabled")
parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help="Enable debugging output")
parser.add_option("-b", "--background", action="store_true", dest="background", default=False, help="Run in the background and monitor virtual guests")
parser.add_option("-o", "--one-shot", action="store_true", dest="oneshot", default=False, help="Send the list of guest IDs and exit immediately")
parser.add_option("-i", "--interval", type="int", dest="interval", default=0, help="Acquire and send list of virtual guest each N seconds")
- parser.add_option("--libvirt", action="store_const", dest="virtType", const="libvirt", default="libvirt", help="Use libvirt to list virtual guests [default]")
- parser.add_option("--vdsm", action="store_const", dest="virtType", const="vdsm", help="Use vdsm to list virtual guests")
- parser.add_option("--esx", action="store_const", dest="virtType", const="esx", help="Register ESX machines using vCenter")
- parser.add_option("--rhevm", action="store_const", dest="virtType", const="rhevm", help="Register guests using RHEV-M")
- parser.add_option("--hyperv", action="store_const", dest="virtType", const="hyperv", help="Register guests using Hyper-V")
+
+ virtGroup = OptionGroup(parser, "Virtualization backend", "Choose virtualization backend that should be used to gather host/guest associations")
+ virtGroup.add_option("--libvirt", action="store_const", dest="virtType", const="libvirt", default="libvirt", help="Use libvirt to list virtual guests [default]")
+ virtGroup.add_option("--vdsm", action="store_const", dest="virtType", const="vdsm", help="Use vdsm to list virtual guests")
+ virtGroup.add_option("--esx", action="store_const", dest="virtType", const="esx", help="Register ESX machines using vCenter")
+ virtGroup.add_option("--rhevm", action="store_const", dest="virtType", const="rhevm", help="Register guests using RHEV-M")
+ virtGroup.add_option("--hyperv", action="store_const", dest="virtType", const="hyperv", help="Register guests using Hyper-V")
+ parser.add_option_group(virtGroup)
+
+ managerGroup = OptionGroup(parser, "Subscription manager", "Choose where the host/guest associations should be reported")
+ managerGroup.add_option("--sam", action="store_const", dest="smType", const="sam", help="Report host/guest associations to the Subscription Asset Manager [default]")
+ managerGroup.add_option("--satellite", action="store_const", dest="smType", const="satellite", help="Report host/guest associations to the Satellite")
+ parser.add_option_group(managerGroup)
esxGroup = OptionGroup(parser, "vCenter/ESX options", "Use this options with --esx")
esxGroup.add_option("--esx-owner", action="store", dest="owner", default="", help="Organization who has purchased subscriptions of the products")
@@ -354,6 +374,12 @@ def main():
hypervGroup.add_option("--hyperv-password", action="store", dest="password", default="", help="Password for connecting to Hyper-V")
parser.add_option_group(hypervGroup)
+ satelliteGroup = OptionGroup(parser, "Satellite options", "Use this options with --satellite")
+ satelliteGroup.add_option("--satellite-server", action="store", dest="sat_server", default="", help="Satellite server URL")
+ satelliteGroup.add_option("--satellite-username", action="store", dest="sat_username", default="", help="Username for connecting to Satellite server")
+ satelliteGroup.add_option("--satellite-password", action="store", dest="sat_password", default="", help="Password for connecting to Satellite server")
+ parser.add_option_group(satelliteGroup)
+
(options, args) = parser.parse_args()
# Handle enviromental variables
@@ -379,6 +405,14 @@ def main():
except ValueError:
logger.warning("Interval is not number, ignoring")
+ env = os.getenv("VIRTWHO_SAM", "0").strip().lower()
+ if env in ["1", "true"]:
+ options.smType = "sam"
+
+ env = os.getenv("VIRTWHO_SATELLITE", "0").strip().lower()
+ if env in ["1", "true"]:
+ options.smType = "satellite"
+
env = os.getenv("VIRTWHO_VDSM", "0").strip().lower()
if env in ["1", "true"]:
options.virtType = "vdsm"
@@ -408,6 +442,16 @@ def main():
sys.exit(1)
return option
+ if options.smType == "satellite":
+ options.sat_server = checkEnv("VIRTWHO_SATELLITE_SERVER", options.sat_server, "satellite-server")
+ if len(options.sat_username) == 0:
+ options.sat_username = os.getenv("VIRTWHO_SATELLITE_USERNAME", "")
+ if len(options.sat_password) == 0:
+ options.sat_password = os.getenv("VIRTWHO_SATELLITE_PASSWORD", "")
+
+ if len(options.sat_username) == 0:
+ logger.info('Satellite username is not specified, assuming preregistered system')
+
if options.virtType == "esx":
options.owner = checkEnv("VIRTWHO_ESX_OWNER", options.owner, "owner")
options.env = checkEnv("VIRTWHO_ESX_ENV", options.env, "env")
10 years, 9 months
[virt-who] vsphere: Handle more than 100 objects in esx traversal
by Radek Novacek
commit 13eb4458af0f1b6746f9b7103a5204e6c0a3bea0
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Wed Aug 28 15:44:41 2013 +0200
vsphere: Handle more than 100 objects in esx traversal
RetrievePropertiesEx might return just partial result and virt-who now
calls ContinueRetrievePropertiesEx in order to get all results.
vsphere.py | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
---
diff --git a/vsphere.py b/vsphere.py
index e8e1145..5109e08 100644
--- a/vsphere.py
+++ b/vsphere.py
@@ -264,11 +264,14 @@ class VSphere:
# Query the VSphere server
try:
- retrieve_result = self.client.service.RetrievePropertiesEx(_this=self.sc.propertyCollector, specSet=[pfs])
+ retrieve_result = result = self.client.service.RetrievePropertiesEx(_this=self.sc.propertyCollector, specSet=[pfs])
+ while hasattr(result, "token"):
+ result = self.client.service.ContinueRetrievePropertiesEx(_this=self.sc.propertyCollector, token=retrieve_result.token)
+ retrieve_result.objects += result.objects
if retrieve_result is None:
return []
else:
- return retrieve_result[0]
+ return retrieve_result.objects
except suds.MethodNotFound:
return self.client.service.RetrieveProperties(_this=self.sc.propertyCollector, specSet=[pfs])
10 years, 9 months
[virt-who/satellite] Optimize creating satellite plan a little
by Radek Novacek
commit f8684120205a8b1ccf30844e4eb2a6cfd9daf286
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Tue Aug 27 15:48:27 2013 +0200
Optimize creating satellite plan a little
satellite.py | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
---
diff --git a/satellite.py b/satellite.py
index 3a98beb..055719c 100644
--- a/satellite.py
+++ b/satellite.py
@@ -132,12 +132,12 @@ class Satellite(object):
def hypervisorCheckIn(self, owner, env, mapping, type=None):
- for hypervisor_uuid in mapping:
+ for hypervisor_uuid, guest_uuids in mapping.items():
self.logger.debug("Loading systemid for %s" % hypervisor_uuid)
hypervisor_systemid = self._load_hypervisor(hypervisor_uuid, type=type)
- self.logger.debug("Building plan for hypervisor %s: %s" % (hypervisor_uuid, mapping[hypervisor_uuid]))
- plan = self._assemble_plan(mapping[hypervisor_uuid], hypervisor_uuid, type = type)
+ self.logger.debug("Building plan for hypervisor %s: %s" % (hypervisor_uuid, guest_uuids))
+ plan = self._assemble_plan(guest_uuids, hypervisor_uuid, type=type)
try:
self.logger.debug("Sending plan: %s" % plan)
10 years, 9 months
[virt-who/satellite] Require username to be present
by Radek Novacek
commit f376020c0e6003336491d0d8a95dd8aed53c2347
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Tue Aug 27 15:47:33 2013 +0200
Require username to be present
Username is now required because new hypervisor may appear anytime
virt-who.py | 6 +-----
1 files changed, 1 insertions(+), 5 deletions(-)
---
diff --git a/virt-who.py b/virt-who.py
index 36c2f90..88b8e37 100644
--- a/virt-who.py
+++ b/virt-who.py
@@ -444,14 +444,10 @@ def main():
if options.smType == "satellite":
options.sat_server = checkEnv("VIRTWHO_SATELLITE_SERVER", options.sat_server, "satellite-server")
- if len(options.sat_username) == 0:
- options.sat_username = os.getenv("VIRTWHO_SATELLITE_USERNAME", "")
+ options.sat_username = checkEnv("VIRTWHO_SATELLITE_USERNAME", options.sat_username, "satellite-username")
if len(options.sat_password) == 0:
options.sat_password = os.getenv("VIRTWHO_SATELLITE_PASSWORD", "")
- if len(options.sat_username) == 0:
- logger.info('Satellite username is not specified, assuming preregistered system')
-
if options.virtType == "esx":
options.owner = checkEnv("VIRTWHO_ESX_OWNER", options.owner, "owner")
options.env = checkEnv("VIRTWHO_ESX_ENV", options.env, "env")
10 years, 9 months
[virt-who/satellite] register one system per hypervisor
by Radek Novacek
commit 02d7a24eaceafd86af6d4053a59aeb84693f4183
Author: Chris Duryee <cduryee(a)redhat.com>
Date: Mon Aug 26 20:43:16 2013 -0400
register one system per hypervisor
Previously, each cluster was registered as a single system. Instead, register
each hypervisor individually.
Also, use more descriptive hypervisor system names that include UUID and virt
type.
Makefile | 1 -
satellite.py | 161 +++++++++++++++++--------------------------
subscriptionmanager.py | 2 +-
virt-who-register-satellite | 10 ---
virt-who.py | 2 +-
virt-who.spec | 1 -
6 files changed, 64 insertions(+), 113 deletions(-)
---
diff --git a/Makefile b/Makefile
index 5331a4a..6dee540 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,6 @@ install:
install -d $(DESTDIR)/usr/share/$(name)/ $(DESTDIR)/usr/bin $(DESTDIR)/etc/rc.d/init.d $(DESTDIR)/etc/sysconfig $(DESTDIR)/usr/share/man/man8/
install -pm 0644 *.py $(DESTDIR)/usr/share/$(name)/
install virt-who $(DESTDIR)/usr/bin/
- install virt-who-register-satellite $(DESTDIR)/usr/bin/
install virt-who-initscript $(DESTDIR)/etc/rc.d/init.d/virt-who
install -pm 0644 virt-who.conf $(DESTDIR)/etc/sysconfig/virt-who
gzip -c virt-who.8 > virt-who.8.gz
diff --git a/satellite.py b/satellite.py
index e25ae15..3a98beb 100644
--- a/satellite.py
+++ b/satellite.py
@@ -32,19 +32,20 @@ class SatelliteError(Exception):
class Satellite(object):
""" Class for interacting with satellite (RHN Classic). """
- VAR_DIR = "/var/lib/virt-who/"
- HYPERVISOR_SYSTEMID_FILE = VAR_DIR + "hypervisor-systemid"
+ HYPERVISOR_SYSTEMID_FILE="/var/lib/virt-who/hypervisor-systemid-%s"
def __init__(self, logger):
self.logger = logger
self.server = None
def connect(self, server, username, password, options=None, force_register=False):
- # initialize a new system if one doesn't already exist
if not server.startswith("http://") and not server.startswith("https://"):
server = "https://%s" % server
if not server.endswith("XMLRPC"):
server = "%s/XMLRPC" % server
+ self.username = username
+ self.password = password
+
self.logger.debug("Initializing satellite connection to %s" % server)
try:
self.server = xmlrpclib.Server(server, verbose=0)
@@ -53,54 +54,36 @@ class Satellite(object):
raise SatelliteError("Unable to connect to the Satellite server")
self.logger.info("Initialized satellite connection")
- # initialize a new system if one doesn't already exist
- if force_register:
- new_system = self._register_hypervisor(username, password, options)
- else:
- try:
- self.logger.debug("Loading system id info from %s" % self.HYPERVISOR_SYSTEMID_FILE)
- new_system = pickle.load(open(self.HYPERVISOR_SYSTEMID_FILE, "rb"))
- except IOError:
- new_system = self._register_hypervisor(username, password, options)
-
- if new_system is None:
- raise SatelliteError("Unable to register hypervisor")
-
- self.systemid = new_system["system_id"]
-
- def _register_hypervisor(self, username, password, options):
- if options is None:
- # We need to emulate options object from argparse
- class O(object): pass
- options = O()
- # Fill in some defaults
- if not hasattr(options, "profile_name") or options.profile_name is None:
- options.profile_name = "hypervisor"
- if not hasattr(options, "os_release_name") or options.os_release_name is None:
- options.os_release_name = "unknown"
- if not hasattr(options, "version") or options.version is None:
- # TODO: what to do here? 6Server will consume subscription
- options.version = "6Server"
- if not hasattr(options, "arch") or options.arch is None:
- options.arch = "x86_64"
-
+ def _load_hypervisor(self, hypervisor_uuid, type):
+ systemid_filename = self.HYPERVISOR_SYSTEMID_FILE % hypervisor_uuid
+ # attempt to read the existing systemid file for the hypervisor
try:
- new_system = self.server.registration.new_system_user_pass(options.profile_name,
- options.os_release_name, options.version, options.arch, username, password, {})
- self.server.registration.refresh_hw_profile(new_system['system_id'], [])
- except Exception, e:
- self.logger.exception("Unable to refresh HW profile")
- raise SatelliteError("Unable to refresh HW profile: %s" % str(e))
- try:
- f = open(self.HYPERVISOR_SYSTEMID_FILE, "w")
+ self.logger.debug("Loading system id info from %s" % systemid_filename)
+ new_system = pickle.load(open(systemid_filename, "rb"))
+ except IOError:
+ # assume file was not found, create a new hypervisor
+ try:
+ # TODO: what to do here? 6Server will consume subscription
+ new_system = self.server.registration.new_system_user_pass("%s hypervisor %s" % (type, hypervisor_uuid),
+ "unknown", "6Server", "x86_64", self.username, self.password, {})
+ self.server.registration.refresh_hw_profile(new_system['system_id'], [])
+ except Exception, e:
+ self.logger.exception("Unable to refresh HW profile")
+ raise SatelliteError("Unable to refresh HW profile: %s" % str(e))
+ # save the hypervisor systemid
try:
- pickle.dump(new_system, f)
- finally:
- f.close()
- except (OSError, IOError), e:
- self.logger.error("Unable to write system id to %s: %s" % (self.HYPERVISOR_SYSTEMID_FILE, str(e)))
+ f = open(systemid_filename, "w")
+ try:
+ pickle.dump(new_system, f)
+ finally:
+ f.close()
+ except (OSError, IOError), e:
+ self.logger.error("Unable to write system id to %s: %s" % (systemid_filename, str(e)))
- self.logger.debug("New system created in satellite, system id saved in %s" % self.HYPERVISOR_SYSTEMID_FILE)
+ self.logger.debug("New system created in satellite, system id saved in %s" % systemid_filename)
+
+ if new_system is None:
+ raise SatelliteError("Unable to register hypervisor %s" % hypervisor_uuid)
return new_system
@@ -110,8 +93,10 @@ class Satellite(object):
"""
pass
- def _assemble_plan(self, uuids):
+ def _assemble_plan(self, hypervisor_mapping, hypervisor_uuid, type):
+ # Get rid of dashes from UUID, spacewalk does not like them
+ #hypervisor_uuid = (str(hypervisor_uuid).replace("-", ""))
events = []
# the stub_instance_info is not used by the report. When the guest system checks in, it will provide
@@ -121,17 +106,23 @@ class Satellite(object):
'memory_size' : 0,
'virt_type' : 'fully_virtualized',
'state' : 'running',
- # TODO: put hypervisor's hostname here maybe
- 'name': "virtual machine from %s" % 'vmware hypervisor'
}
- # declare the hypervisor. always use 16 zeros for the hypervisor's UUID, per rhn-virtualization-host
- events.append([0, 'exists', 'system', {'identity': 'host', 'uuid': self.uuid()}])
+ # again, remove dashes
+ guest_uuids = []
+ for g_uuid in hypervisor_mapping:
+ guest_uuids.append(str(g_uuid).replace("-", ""))
+
+
+ # TODO: spacewalk wants all zeroes for the hypervisor uuid??
+ events.append([0, 'exists', 'system', {'identity': 'host', 'uuid': '0000000000000000'}])
events.append([0, 'crawl_began', 'system', {}])
- for uuid in uuids:
- stub_instance_info['uuid'] = uuid
+ for guest_uuid in guest_uuids:
+ stub_instance_info['uuid'] = guest_uuid
+ stub_instance_info['name'] = "VM from %s hypervisor %s" % (type, hypervisor_uuid)
events.append([0, 'exists', 'domain', stub_instance_info.copy()])
+
events.append([0, 'crawl_ended', 'system', {}])
return events
@@ -139,27 +130,21 @@ class Satellite(object):
def sendVirtGuests(self, domains):
raise SatelliteError("virt-who does not support sending local hypervisor data to satellite; use rhn-virtualization-host instead")
- def hypervisorCheckIn(self, owner, env, mapping):
- self.logger.debug("Building plan for mapping: %s" % mapping)
- if self.server is None:
- return
- uuids = []
- for guestlist in mapping.values():
- for uuid in guestlist:
- # Get rid of dashes from UUID
- uuids.append(str(uuid).replace("-", ""))
- uuids.sort()
-
- self.logger.debug("Sending flattened list of uuids: %s" % uuids)
-
- plan = self._assemble_plan(uuids)
- self.logger.debug("Sending plan: %s" % plan)
- # Send the mapping
- try:
- res = self.server.registration.virt_notify(self.systemid, plan)
- except Exception, e:
- self.logger.exception("Unable to send host/guest assocaition to the satellite:")
- raise SatelliteError("Unable to send host/guest assocaition to the satellite: % " % str(e))
+ def hypervisorCheckIn(self, owner, env, mapping, type=None):
+
+ for hypervisor_uuid in mapping:
+ self.logger.debug("Loading systemid for %s" % hypervisor_uuid)
+ hypervisor_systemid = self._load_hypervisor(hypervisor_uuid, type=type)
+
+ self.logger.debug("Building plan for hypervisor %s: %s" % (hypervisor_uuid, mapping[hypervisor_uuid]))
+ plan = self._assemble_plan(mapping[hypervisor_uuid], hypervisor_uuid, type = type)
+
+ try:
+ self.logger.debug("Sending plan: %s" % plan)
+ self.server.registration.virt_notify(hypervisor_systemid["system_id"], plan)
+ except Exception, e:
+ self.logger.exception("Unable to send host/guest assocaition to the satellite:")
+ raise SatelliteError("Unable to send host/guest assocaition to the satellite: % " % str(e))
# TODO: figure out what to populate here
result = {}
@@ -169,31 +154,9 @@ class Satellite(object):
return result
def uuid(self):
- """ Satellite expects a zeroed-out hypervisor UUID """
+ """ not implemented """
return '0000000000000000'
def getFacts(self):
""" Not implemented """
pass
-
-if __name__ == '__main__':
- from optparse import OptionParser
- import logging
- parser = OptionParser(usage="virt-who-register-satellite [-n name] [-o operating_system] [-v version] [-a arch] server username password",
- description="Register hypervisor to the satellite server")
- parser.add_option("-n", "--name", action="store", dest="profile_name", default=None, help="Name of the hypervisor")
- parser.add_option("-o", "--operating-system", action="store", dest="os_release_name", default=None, help="Operating system of the hypervisor")
- parser.add_option("-v", "--version", action="store", dest="version", default=None, help="Operating system version")
- parser.add_option("-a", "--arch", action="store", dest="arch", default=None, help="Hypervisor architecture")
- (options, args) = parser.parse_args()
- if len(args) < 3:
- parser.print_usage()
- sys.exit(1)
-
- logger = logging.getLogger()
- logger.addHandler(logging.StreamHandler())
- satellite = Satellite(logger)
- try:
- satellite.connect(args[0], args[1], args[2], force_register=True, options=options)
- except Exception:
- logger.exception("Unable to connect to Satellite:")
diff --git a/subscriptionmanager.py b/subscriptionmanager.py
index 6dc2482..51345d9 100644
--- a/subscriptionmanager.py
+++ b/subscriptionmanager.py
@@ -83,7 +83,7 @@ class SubscriptionManager:
# Send list of guest uuids to the server
self.connection.updateConsumer(self.uuid(), guest_uuids=uuids)
- def hypervisorCheckIn(self, owner, env, mapping):
+ def hypervisorCheckIn(self, owner, env, mapping, type=None):
""" Send hosts to guests mapping to subscription manager. """
self.logger.debug("Sending update in hosts-to-guests mapping: %s" % mapping)
diff --git a/virt-who.py b/virt-who.py
index 53051ef..36c2f90 100644
--- a/virt-who.py
+++ b/virt-who.py
@@ -204,7 +204,7 @@ class VirtWho(object):
if self.options.virtType not in ["esx", "rhevm", "hyperv"]:
self.subscriptionManager.sendVirtGuests(virtualGuests)
else:
- result = self.subscriptionManager.hypervisorCheckIn(self.options.owner, self.options.env, virtualGuests)
+ result = self.subscriptionManager.hypervisorCheckIn(self.options.owner, self.options.env, virtualGuests, type=self.options.virtType)
# Show the result of hypervisorCheckIn
for fail in result['failedUpdate']:
diff --git a/virt-who.spec b/virt-who.spec
index cd37072..1dc936d 100644
--- a/virt-who.spec
+++ b/virt-who.spec
@@ -64,7 +64,6 @@ fi
%files
%doc README LICENSE
%{_bindir}/virt-who
-%{_bindir}/virt-who-register-satellite
%{_datadir}/virt-who/
%{_sysconfdir}/rc.d/init.d/virt-who
%config(noreplace) %{_sysconfdir}/sysconfig/virt-who
10 years, 9 months
[virt-who/satellite] spec: create /var dir in the spec instead of source
by Radek Novacek
commit 6269176d3ab3b063e92f137b446e177a1084ee60
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Aug 26 10:28:25 2013 +0200
spec: create /var dir in the spec instead of source
Also install virt-who-register-satellite
satellite.py | 2 --
virt-who.spec | 3 +++
2 files changed, 3 insertions(+), 2 deletions(-)
---
diff --git a/satellite.py b/satellite.py
index 14433d4..e25ae15 100644
--- a/satellite.py
+++ b/satellite.py
@@ -92,8 +92,6 @@ class Satellite(object):
self.logger.exception("Unable to refresh HW profile")
raise SatelliteError("Unable to refresh HW profile: %s" % str(e))
try:
- if not os.path.isdir(self.VAR_DIR):
- os.mkdir(self.VAR_DIR, 0600)
f = open(self.HYPERVISOR_SYSTEMID_FILE, "w")
try:
pickle.dump(new_system, f)
diff --git a/virt-who.spec b/virt-who.spec
index 75ea8f7..cd37072 100644
--- a/virt-who.spec
+++ b/virt-who.spec
@@ -37,6 +37,7 @@ report them to the subscription manager.
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
+mkdir -p %{buildroot}/%{_sharedstatedir}/%{name}
# Don't run test suite in check section, because it need the system to be
# registered to subscription-manager server
@@ -63,10 +64,12 @@ fi
%files
%doc README LICENSE
%{_bindir}/virt-who
+%{_bindir}/virt-who-register-satellite
%{_datadir}/virt-who/
%{_sysconfdir}/rc.d/init.d/virt-who
%config(noreplace) %{_sysconfdir}/sysconfig/virt-who
%{_mandir}/man8/virt-who.8.gz
+%{_sharedstatedir}/%{name}
%changelog
10 years, 9 months
[virt-who/satellite] Handle exceptions in virt_notify function
by Radek Novacek
commit c5f755b99523cd478f72bf14b21403f47924575d
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Aug 26 10:20:35 2013 +0200
Handle exceptions in virt_notify function
satellite.py | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
---
diff --git a/satellite.py b/satellite.py
index 0e42d70..14433d4 100644
--- a/satellite.py
+++ b/satellite.py
@@ -157,7 +157,11 @@ class Satellite(object):
plan = self._assemble_plan(uuids)
self.logger.debug("Sending plan: %s" % plan)
# Send the mapping
- res = self.server.registration.virt_notify(self.systemid, plan)
+ try:
+ res = self.server.registration.virt_notify(self.systemid, plan)
+ except Exception, e:
+ self.logger.exception("Unable to send host/guest assocaition to the satellite:")
+ raise SatelliteError("Unable to send host/guest assocaition to the satellite: % " % str(e))
# TODO: figure out what to populate here
result = {}
10 years, 9 months