Declare what URI schemes a driver supports in its virConnectDriver
struct. This allows us to skip trying to open the driver entirely
if the URI scheme doesn't match.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Lists in Python are mutable and when used as a default value of a
parameter for class constructor, its value will be shared between
all class instances.
Example:
class Test:
def __init__(self, mylist=[]):
self.mylist = mylist
A = Test()
B = Test()
A.mylist.append("mylist from instance A")
print(B.mylist) # Will print ['mylist from instance A']
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
PEP8 recommends removing whitespace immediately before a comma,
semicolon, or colon [1]. In addition remove multiple spaces after
keyword (PEP8 - E271).
1: https://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Some of our scripts are known to work both with Python 2 and
Python 3, so for them we shouldn't be forcing any specific
version of the interpreter when they're called directly; we
always use $(PYTHON) explicitly in our build rules anyway.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This deals with cls.version possibly being None.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
We use text operations on the contents after reading them.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
The keys() method no longer returns a list, so converting the
return value would be necessary before calling sort() on it;
alternatively, we can just call sorted(), which returns a
sorted list.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Ensure all enum cases are listed in switch statements. This improves
debug logging integration with openwsman.
Reviewed-by: John Ferlan <jferlan@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Hyper-V uses its own specific memory management so no mapping is going to
be perfect. However, it is more correct to map Limit to max_memory (it
really is the upper limit of what the VM may potentially use) and keep
cur_balloon equal to total_memory.
The typical value returned from Hyper-V in Limit is 1 TiB, which is not
really going to work if interpreted as "startup memory" to be ballooned
away later.
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
The code was vulnerable to SQL injection. Likely not a security issue due to
WMI SQL and other constraints but still lame. For example:
virsh # dominfo \"
error: failed to get domain '"'
error: internal error: SOAP fault during enumeration: code 's:Sender', subcode
'n:CannotProcessFilter', reason 'The data source could not process the filter.
The filter might be missing or it might be invalid. Change the filter and try
the request again. ', detail 'The WS-Management service cannot process the
request. The WQL query is invalid. '
This commit fixes the Hyper-V driver by escaping all WMI SQL string parameters.
The same command with the fix:
virsh # dominfo \"
error: failed to get domain '"'
error: Domain not found: No domain with name "
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
"%s is not a Hyper-V server" is not a correct generalization of all possible
error conditions of hypervEnumAndPull. For example:
$ virsh --connect hyperv://localhost/?transport=http
Enter username for localhost [administrator]:
Enter administrator's password for localhost: <enters incorrect password>
error: failed to connect to the hypervisor
error: internal error: localhost is not a Hyper-V server
This commit removes the general virReportError from hypervInitConnection and
also the "Invalid query" virReportError from hypervSerializeEprParam, which
does not correctly describe the error either (virBufferCheckError has
already set a meaningful error message at that point).
The same scenario with the fix:
$ virsh --connect hyperv://localhost/?transport=http
Enter username for localhost [administrator]:
Enter administrator's password for localhost: <enters incorrect password>
error: failed to connect to the hypervisor
error: internal error: Transport error during enumeration: User, password or
similar was not accepted (26)
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
This is particularly useful on operating systems that don't ship
Python as part of the base system (eg. FreeBSD) while still working
just as well as it did before on Linux.
While at it, make it explicit that our scripts are only going to
work with Python 2, and remove the usage of unbuffered I/O, which
as far as I can tell has no effect on the output files.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Slight refactor of the WMI serialization code to minimize mixing
openwsman and libxml2 APIs that triggered clang alignment warnings.
The only usage of libxml2 APIs now is in creating CDATA blocks,
because the openwsman API does not provide that functionality. The
clang alignment warning in this case is silenced by casting to a
void pointer first.
Introduces support for virDomainSetMemory. This also serves an an
example for how to use the new method invocation API with a more
complicated method, this time including an EPR and embedded param.
This commit adds support for virDomainSendKey. It also serves as an
example of how to use the new method invocation APIs with a single
"simple" type parameter.
Update the generator to generate basic property type information for
each CIM object representation. Right now, it generates arrays of
hypervCimType structs:
struct _hypervCimType {
const char *name;
const char *type;
bool isArray;
};
This commit introduces functionality for creating and working with
invoke parameters. This commit does not include any code for serializing
and actually performing the method invocations; it merely defines the
functions and API for using invocation parameters in driver code.
HYPERV_DEFAULT_PARAM_COUNT was chosen because almost no method
invocations have more than 4 parameters.
Functions added:
* hypervInitInvokeParamsList
* hypervFreeInvokeParams
* hypervAddSimpleParam
* hypervAddEprParam
* hypervCreateEmbeddedParam
* hypervSetEmbeddedProperty
* hypervAddEmbeddedParam
* hypervFreeEmbeddedParam
When hyperv code generator for WMI classes identifies common
properties, it needs to take into account array type as a distinct
type, i.e string != string[]. This is the case where v1 of the
Msvm_VirtualSystemSettingData has Notes property as string whereas v2
uses Notes[], therefore they have to be treated as different fields and
cannot be placed in the "common" struct.
This patch reworks the Hyper-V driver structs and the code generator
to provide seamless support for both Hyper-V 2008 and 2012 or newer.
This does not implement any new libvirt APIs, it just adapts existing
2008-only driver to also handle 2012 and newer by sharing as much
driver code as possible (currently it's all of it :-)). This is needed
to set the foundation before we can move forward with implementing the
rest of the driver APIs.
With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI
classes. Those are largely the same as "v1" (used in 2008) but have some
new properties as well as need different wsman request URIs. To
accomodate those differences, most of work went into the code generator
so that it's "aware" of possibility of multiple versions of the same WMI
class and produce C code accordingly.
To accomplish this the following changes were made:
* the abstract hypervObject struct's data member was changed to a union
that has "common", "v1" and "v2" members. Those are structs that
represent WMI classes that we get back from wsman response. The
"common" struct has members that are present in both "v1" and "v2"
which the driver API callbacks can use to read the data from in
version-independent manner (if version-specific member needs to be
accessed the driver can check priv->wmiVersion and read from "v1" or
"v2" as needed). Those structs are guaranteed to be memory aligned
by the code generator (see the align_property_members implementation
that takes care of that)
* the generator produces *_WmiInfo for each WMI class "family" that
holds an array of hypervWmiClassInfoPtr each providing information
as to which request URI to use for each "version" of given WMI class
as well as XmlSerializerInfo struct needed to unserilize WS-MAN
responsed into the data structs. The driver uses those to make proper
WS-MAN request depending on which version it's connected to.
* the generator no longer produces "helper" functions such as
hypervGetMsvmComputerSystemList as those were originally just simple
wrappers around hypervEnumAndPull, instead those were hand-written
now (to keep driver changes minimal). The reason is that we'll have
more code coming implementing missing libvirt APIs and surely code
patterns will emerge that would warrant more useful "utility" functions
like that.
* a hypervInitConnection was added to the driver which "detects"
Hyper-V version by testing simple wsman request using v2 then falling
back to v1, obviously if both fail, the we're erroring out.
To express how the above translates in code:
void
hypervImplementSomeLibvirtApi(virConnectPtr conn, ...)
{
hypervPrivate *priv = conn->privateData;
virBuffer query = VIR_BUFFER_INITIALIZER;
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */
/* the WmiInfo struct has the data needed for wsman request and
* response handling for both v1 and v2 */
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
wqlQuery.query = &query;
virBufferAddLit(&query, "select * from Msvm_ComputerSystem");
if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) {
goto cleanup;
}
if (list == NULL) {
/* none found */
goto cleanup;
}
/* works with v1 and v2 */
char *vmName = list->data.common->Name;
/* access property that is in v2 only */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2)
char *foo = list->data.v2->V2Property;
else
char *foo = list->data.v1->V1Property;
cleanup:
hypervFreeObject(priv, (hypervObject *)list);
}
Currently named as hypervObjecUnified to keep code
compilable/functional until all bits are in place.
This struct is a result of unserializing WMI request response.
Therefore, it needs to be able to deal with different "versions" of the
same WMI class. To accomplish this, the "data" member was turned in to
a union which:
* has a "common" member that contains only WMI class fields that are
safe to access and are present in all "versions". This is ensured by
the code generator that takes care of proper struct memory alignment
between "common", "v1", "v2" etc members. This memeber is to be used
by the driver code wherever the API implementation can be shared for
all supported hyper-v versions.
* the "v1" and "v2" member can be used by the driver code to handle
version specific cases.
Example:
Msvm_ComputerSystem *vm = NULL;
...
hypervGetVirtualMachineList(priv, wqlQuery, *vm);
...
/* safe for "v1" and "v2" */
char *vmName = vm->data.common->Name;
/* or if one really needs special handling for "v2" */
if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
char *foo = vm->data.v2->SomeV2OnlyField;
}
In other words, driver should not concern itself with existence of "v1"
or "v2" of WMI class unless absolutely necessary.
This struct is to be used to carry all the information necessary to
issue wsman requests for given WMI class. Those will be defined by the
generator code (as lists) so that they are handy for the driver code to
"extract" needed info depending on which hyper-v we're connected to.
For example:
hypervWmiClassInfoListPtr Msvm_ComputerSystem_WmiInfo = {
.count = 2
{
{
.name = "Msvm_ComputerSystem",
.version = "v1",
.rootUri = "http://asdf.com",
...
},
{
.name = "Msvm_ComputerSystem",
.version = "v2",
.rootUri = "http://asdf.com/v2",
...
},
}
};
Then the driver code will grab either "v1" or "v2" to pass info wsman
API, depending on hypervPrivate->wmiVersion value.
Hyper-V 2012+ uses a new "v2" version of Msvm_* WMI classes so we will
store that info in hypervPrivate so that it is easily accessbile in the
driver API callbacks and handled accordingly.
So far our code is full of the following pattern:
dom = virGetDomain(conn, name, uuid)
if (dom)
dom->id = 42;
There is no reasong why it couldn't be just:
dom = virGetDomain(conn, name, uuid, id);
After all, client domain representation consists of tuple (name,
uuid, id).
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Allow to store driver specific data on a per-vcpu basis.
Move of the virDomainDef*Vcpus* functions was necessary as
virDomainXMLOptionPtr was declared below this block and I didn't want to
split the function headers.
The virConnectOpenInternal method opens the libvirt client
config file and uses it to resolve things like URI aliases.
There may be driver specific things that are useful to
store in the config file too, so rather than have them
re-parse the same file, pass the virConfPtr down to the
drivers.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
And use the newly added caps->host.netprefix (if it exists) for
interface names that match the autogenerated target names.
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Our domain_conf.* files are big enough. Not only they contain XML
parsing code, but they served as a storage of all functions whose
name is virDomain prefixed. This is just wrong as it gathers not
related functions (and modules) into one big file which is then
harder to maintain. Split virDomainObjList module into a separate
file called virdomainobjlist.[ch].
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
As there are two possible approaches to define a domain's memory size -
one used with legacy, non-NUMA VMs configured in the <memory> element
and per-node based approach on NUMA machines - the user needs to make
sure that both are specified correctly in the NUMA case.
To avoid this burden on the user I'd like to replace the NUMA case with
automatic totaling of the memory size. To achieve this I need to replace
direct access to the virDomainMemtune's 'max_balloon' field with
two separate getters depending on the desired size.
The two sizes are needed as:
1) Startup memory size doesn't include memory modules in some
hypervisors.
2) After startup these count as the usable memory size.
Note that the comments for the functions are future aware and document
state that will be present after a few later patches.
For stateless, client side drivers, it is never correct to
probe for secondary drivers. It is only ever appropriate to
use the secondary driver that is associated with the
hypervisor in question. As a result the ESX & HyperV drivers
have both been forced to do hacks where they register no-op
drivers for the ones they don't implement.
For stateful, server side drivers, we always just want to
use the same built-in shared driver. The exception is
virtualbox which is really a stateless driver and so wants
to use its own server side secondary drivers. To deal with
this virtualbox has to be built as 3 separate loadable
modules to allow registration to work in the right order.
This can all be simplified by introducing a new struct
recording the precise set of secondary drivers each
hypervisor driver wants
struct _virConnectDriver {
virHypervisorDriverPtr hypervisorDriver;
virInterfaceDriverPtr interfaceDriver;
virNetworkDriverPtr networkDriver;
virNodeDeviceDriverPtr nodeDeviceDriver;
virNWFilterDriverPtr nwfilterDriver;
virSecretDriverPtr secretDriver;
virStorageDriverPtr storageDriver;
};
Instead of registering the hypervisor driver, we now
just register a virConnectDriver instead. This allows
us to remove all probing of secondary drivers. Once we
have chosen the primary driver, we immediately know the
correct secondary drivers to use.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The virDomainDefParse* and virDomainDefFormat* methods both
accept the VIR_DOMAIN_XML_* flags defined in the public API,
along with a set of other VIR_DOMAIN_XML_INTERNAL_* flags
defined in domain_conf.c.
This is seriously confusing & error prone for a number of
reasons:
- VIR_DOMAIN_XML_SECURE, VIR_DOMAIN_XML_MIGRATABLE and
VIR_DOMAIN_XML_UPDATE_CPU are only relevant for the
formatting operation
- Some of the VIR_DOMAIN_XML_INTERNAL_* flags only apply
to parse or to format, but not both.
This patch cleanly separates out the flags. There are two
distint VIR_DOMAIN_DEF_PARSE_* and VIR_DOMAIN_DEF_FORMAT_*
flags that are used by the corresponding methods. The
VIR_DOMAIN_XML_* flags received via public API calls must
be converted to the VIR_DOMAIN_DEF_FORMAT_* flags where
needed.
The various calls to virDomainDefParse which hardcoded the
use of the VIR_DOMAIN_XML_INACTIVE flag change to use the
VIR_DOMAIN_DEF_PARSE_INACTIVE flag.
Since virDomainFree will call virObjectUnref anyway, let's just use that
directly so as to avoid the possibility that we inadvertently clear out
a pending error message when using the public API.
Since the secondary drivers are only active when the primary
driver is also the Hyper-V driver, there is no need to use the
different type specific privateData fields.
The function hypervEnumAndPull consumes query on success, but leaked
it on failure. Rather than having to change all callers (many of
them indirect callers through the generated
hypervGetMsvmComputerSystemList), it was easier to just guarantee
that the buffer is cleaned on return from the function.
* src/hyperv/hyperv_wmi.c (hypervEnumAndPull): Don't leak query on
failure.
Signed-off-by: Eric Blake <eblake@redhat.com>
To prepare for introducing a single global driver, rename the
virDriver struct to virHypervisorDriver and the registration
API to virRegisterHypervisorDriver()
Replace:
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
...
}
with:
if (virBufferCheckError(&buf) < 0)
...
This should not be a functional change (unless some callers
misused the virBuffer APIs - a different error would be reported
then)
Any source file which calls the logging APIs now needs
to have a VIR_LOG_INIT("source.name") declaration at
the start of the file. This provides a static variable
of the virLogSource type.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>