[libvirt] [PATCH] qemu: command: drop redundant min_guarantee check
by Cole Robinson
We already reject a VM with min_guarantee early in the VM startup
in qemuProcessStartValidate
---
src/qemu/qemu_command.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 26c19ff..2fb967a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9143,7 +9143,6 @@ qemuBuildCommandLineValidate(virQEMUDriverPtr driver,
if (virMemoryLimitIsSet(def->mem.hard_limit) ||
virMemoryLimitIsSet(def->mem.soft_limit) ||
- def->mem.min_guarantee ||
virMemoryLimitIsSet(def->mem.swap_hard_limit)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Memory tuning is not available in session mode"));
--
2.7.3
8 years, 7 months
[libvirt] [libvirt-php PATCH 00/29] Add PHP7 support and unit tests V2
by Neal Gompa
This patch set is a revision of the first version, taking into account
some of the feedback from Michal Privoznik.
I've done some patch surgery to rebase the patch set on the current
git HEAD, so it should cleanly apply as-is. Additionally, I've squashed
a few commits (mainly some of Remi's patches that were squashable
that should be squashed). This means that Vasiliy's patches are
no longer unnecessarily part of this patch set.
I've updated my patches for the instructions on the php extension build
system method to correct a typo on how to run the tests
(`make test` instead of `make tests`) and removed the "-dev" suffix
that Remi attached to the version string in libvirt-php.h, as I expect
that there will likely be a libvirt-php release after this patch set is merged.
I would greatly appreciate a quick review and merge of this patch set.
Chuck Roydhouse (1):
add arginfo for libvirt_domain_block_commit and
libvirt_domain_block_job_info
Frederic Mora (1):
Add more tests
Neal Gompa (2):
Commit short instructions to using the php extension build method
Bump version to 0.5.2
Remi Collet (25):
add config.m4 to allow standard PHP extension build system
include config.h earlier
add missing arginfo
adapt RETURN_STRING
work on zpp
register + fetch resources + hash
adapt add_assoc_string_ex
clean ALLOC_INIT_ZVAL
zend_hash_update
add_next_index_string
buildable with PHP 7
bump version 0.5.2-dev
fix missed (hidden) zpp calls
fix PHP 5 compat
fix libvirt_version + add test
port test-connect.phpt to real phpt
Switch all add_assoc_string_ex to add_assoc_string to avoid nul char
management
Fix max_connections management
add test-conn-limit.phpt (as real phpt)
add test-connect-get-emulator.phpt
fix parse_array + build warnings
convert test-install.phpt to real phpt
convert test-domain-create-and-coredump.phpt to real phpt
convert test-domain-create-and-get-xpath.phpt to real phpt
fix PHP 5 compat again (nested macro issue)
INSTALL.PHPEXT | 14 +
configure.ac | 2 +-
src/config.m4 | 52 +
src/libvirt-php.c | 1796 ++++++++++++++++-------
src/libvirt-php.h | 48 +-
src/tests/example-no-disk-and-media.xml | 41 +
src/tests/qemu-no-disk-and-media.xml | 41 +
src/tests/skipif.inc | 3 +
src/tests/test-conn-limit.phpt | 49 +
src/tests/test-connect-get-capabilities.phpt | 27 +
src/tests/test-connect-get-emulator.phpt | 15 +
src/tests/test-connect-get-info.phpt | 110 ++
src/tests/test-connect-get-machine-types.phpt | 30 +
src/tests/test-connect.phpt | 15 +
src/tests/test-domain-create-and-coredump.phpt | 49 +
src/tests/test-domain-create-and-get-xpath.phpt | 56 +
src/tests/test-domain-create-and-shutdown.phpt | 38 +
src/tests/test-domain-define.phpt | 38 +
src/tests/test-domain-disk.phpt | 71 +
src/tests/test-domain-get.phpt | 91 ++
src/tests/test-domain-lookup-by-name.phpt | 35 +
src/tests/test-domain-nic.phpt | 52 +
src/tests/test-install.phpt | 136 ++
src/tests/test-libvirt-php.img | 0
src/tests/test-logfile.phpt | 43 +
src/tests/test-version-get.phpt | 27 +
26 files changed, 2330 insertions(+), 549 deletions(-)
create mode 100644 INSTALL.PHPEXT
create mode 100644 src/config.m4
create mode 100644 src/tests/example-no-disk-and-media.xml
create mode 100644 src/tests/qemu-no-disk-and-media.xml
create mode 100644 src/tests/skipif.inc
create mode 100644 src/tests/test-conn-limit.phpt
create mode 100644 src/tests/test-connect-get-capabilities.phpt
create mode 100644 src/tests/test-connect-get-emulator.phpt
create mode 100644 src/tests/test-connect-get-info.phpt
create mode 100644 src/tests/test-connect-get-machine-types.phpt
create mode 100644 src/tests/test-connect.phpt
create mode 100644 src/tests/test-domain-create-and-coredump.phpt
create mode 100644 src/tests/test-domain-create-and-get-xpath.phpt
create mode 100644 src/tests/test-domain-create-and-shutdown.phpt
create mode 100644 src/tests/test-domain-define.phpt
create mode 100644 src/tests/test-domain-disk.phpt
create mode 100644 src/tests/test-domain-get.phpt
create mode 100644 src/tests/test-domain-lookup-by-name.phpt
create mode 100644 src/tests/test-domain-nic.phpt
create mode 100644 src/tests/test-install.phpt
create mode 100644 src/tests/test-libvirt-php.img
create mode 100644 src/tests/test-logfile.phpt
create mode 100644 src/tests/test-version-get.phpt
--
2.5.5
8 years, 7 months
[libvirt] [python PATCH] fix crash in getAllDomainStats
by Pavel Hrdina
Commits 1d39dbaf and 827ed9b4 broke the libvirt-python API by removing
virDomainRef() and virDomainFree(). virDomainStatsRecordListFree() will
free that domain pointer and later when virDomain (python object) call
its destructor and tries to free that same pointer again.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1326839
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
libvirt-override.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/libvirt-override.c b/libvirt-override.c
index 4640ed5..2de95ce 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -8381,6 +8381,7 @@ convertDomainStatsRecord(virDomainStatsRecordPtr *records,
PyObject *py_retval;
PyObject *py_record;
PyObject *py_record_stats = NULL;
+ virDomainPtr dom = NULL;
size_t i;
if (!(py_retval = PyList_New(nrecords)))
@@ -8392,9 +8393,12 @@ convertDomainStatsRecord(virDomainStatsRecordPtr *records,
VIR_PY_LIST_SET_GOTO(py_retval, i, py_record, error);
+ dom = records[i]->dom;
+ virDomainRef(dom);
VIR_PY_TUPLE_SET_GOTO(py_record, 0,
- libvirt_virDomainPtrWrap(records[i]->dom),
+ libvirt_virDomainPtrWrap(dom),
error);
+ dom = NULL;
if (!(py_record_stats = getPyVirTypedParameter(records[i]->params,
records[i]->nparams)))
@@ -8406,6 +8410,8 @@ convertDomainStatsRecord(virDomainStatsRecordPtr *records,
return py_retval;
error:
+ if (dom)
+ virDomainFree(dom);
Py_XDECREF(py_retval);
return NULL;
}
--
2.8.1
8 years, 7 months
[libvirt] [PATCH 0/2] prevent duplicate entries in network device pools
by Laine Stump
This is a simple bugfix, but proper testing required the ability to
test for parse failures in networkxml2xmltest, which wasn't yet an
option, so I added a separate prerequisite patch to do that (in case
someone wants to backport the new testing option without the bugfix).
Laine Stump (2):
test: enable testing for expected parse errors in network XML
network: prevent duplicate entries in network device pools
src/conf/network_conf.c | 33 ++++++++--
tests/networkxml2xmlin/hostdev-duplicate.xml | 11 ++++
tests/networkxml2xmlin/passthrough-duplicate.xml | 10 +++
tests/networkxml2xmltest.c | 77 ++++++++++++++++++------
4 files changed, 108 insertions(+), 23 deletions(-)
create mode 100644 tests/networkxml2xmlin/hostdev-duplicate.xml
create mode 100644 tests/networkxml2xmlin/passthrough-duplicate.xml
--
2.5.5
8 years, 7 months
[libvirt] [PATCH v2] Include sysmacros.h where needed
by Martin Kletzander
So in glibc-2.23 sys/sysmacros.h is no longer included from sys/types.h
and we don't build because of the usage of major/minor/makedev macros.
Autoconf already has AC_HEADER_MAJOR macro that check where exactly
these functions/macros are defined, so let's use that.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
v2:
- Don't include the file unconditionally, but rather use
AC_HEADER_MAJOR that exists for exactly this purpose.
v1:
- https://www.redhat.com/archives/libvir-list/2016-April/msg00851.html
configure.ac | 2 ++
src/conf/domain_audit.c | 6 ++++++
src/lxc/lxc_controller.c | 7 +++++++
src/lxc/lxc_driver.c | 7 +++++++
src/util/vircgroup.c | 7 +++++++
src/util/virutil.c | 7 +++++++
tests/vircgroupmock.c | 7 +++++++
7 files changed, 43 insertions(+)
diff --git a/configure.ac b/configure.ac
index b1500f60bc5d..f266484575ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -144,6 +144,8 @@ AC_TYPE_UID_T
dnl Support building Win32 DLLs (must appear *before* AM_PROG_LIBTOOL)
AC_LIBTOOL_WIN32_DLL
+AC_HEADER_MAJOR
+
m4_ifndef([LT_INIT], [
AM_PROG_LIBTOOL
], [
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index bd2eeb6a792d..36a3cf6ba0b4 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -26,6 +26,12 @@
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+#elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#include "domain_audit.h"
#include "viraudit.h"
#include "viruuid.h"
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 73e57e30ad48..de59775256b5 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -28,6 +28,13 @@
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
+
+#ifdef MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+#elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#include <sys/un.h>
#include <sys/personality.h>
#include <unistd.h>
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index ef488123db12..1dfbde333073 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -29,6 +29,13 @@
#include <sys/utsname.h>
#include <string.h>
#include <sys/types.h>
+
+#ifdef MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+#elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index bffd88f90a44..da5ccff35f8a 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -35,6 +35,13 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
+
+#ifdef MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+#elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#include <signal.h>
#include <dirent.h>
#include <unistd.h>
diff --git a/src/util/virutil.c b/src/util/virutil.c
index 82051505d258..d80d994327cd 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -36,6 +36,13 @@
#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>
+
+#ifdef MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+#elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#include <sys/ioctl.h>
#include <string.h>
#include <termios.h>
diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
index 756ac51679b4..cfc51e8f6373 100644
--- a/tests/vircgroupmock.c
+++ b/tests/vircgroupmock.c
@@ -29,6 +29,13 @@
# include <unistd.h>
# include <fcntl.h>
# include <sys/stat.h>
+
+# ifdef MAJOR_IN_MKDEV
+# include <sys/mkdev.h>
+# elif MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+# endif
+
# include <stdarg.h>
# include "testutilslxc.h"
# include "virstring.h"
--
2.8.1
8 years, 7 months
[libvirt] [PATCH] qemu: Label master key file
by Martin Kletzander
When creating the master key, we used mode 0600 (which we should) but
because we were creating it as root, the file is not readable by any
qemu running as non-root. Fortunately, it's just a matter of labelling
the file. We are generating the file path few times already, so let's
label it in the same function that has access to the path already.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/qemu/qemu_domain.c | 15 ++++++++++++---
src/qemu/qemu_domain.h | 3 ++-
src/qemu/qemu_process.c | 2 +-
3 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 5d54fffcfb98..83e765ef6868 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -504,11 +504,13 @@ qemuDomainGetMasterKeyFilePath(const char *libDir)
* Returns 0 on success, -1 on failure with error message indicating failure
*/
static int
-qemuDomainWriteMasterKeyFile(qemuDomainObjPrivatePtr priv)
+qemuDomainWriteMasterKeyFile(virQEMUDriverPtr driver,
+ virDomainObjPtr vm)
{
char *path;
int fd = -1;
int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
if (!(path = qemuDomainGetMasterKeyFilePath(priv->libDir)))
return -1;
@@ -525,6 +527,10 @@ qemuDomainWriteMasterKeyFile(qemuDomainObjPrivatePtr priv)
goto cleanup;
}
+ if (virSecurityManagerDomainSetDirLabel(driver->securityManager,
+ vm->def, path) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
@@ -697,8 +703,11 @@ qemuDomainMasterKeyRemove(qemuDomainObjPrivatePtr priv)
* Returns: 0 on success, -1 w/ error message on failure
*/
int
-qemuDomainMasterKeyCreate(qemuDomainObjPrivatePtr priv)
+qemuDomainMasterKeyCreate(virQEMUDriverPtr driver,
+ virDomainObjPtr vm)
{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
/* If we don't have the capability, then do nothing. */
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_SECRET))
return 0;
@@ -709,7 +718,7 @@ qemuDomainMasterKeyCreate(qemuDomainObjPrivatePtr priv)
priv->masterKeyLen = QEMU_DOMAIN_MASTER_KEY_LEN;
- if (qemuDomainWriteMasterKeyFile(priv) < 0)
+ if (qemuDomainWriteMasterKeyFile(driver, vm) < 0)
goto error;
return 0;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index d8d57d32df5d..7d2c4fd92ae4 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -584,7 +584,8 @@ char *qemuDomainGetMasterKeyFilePath(const char *libDir);
int qemuDomainMasterKeyReadFile(qemuDomainObjPrivatePtr priv);
-int qemuDomainMasterKeyCreate(qemuDomainObjPrivatePtr priv);
+int qemuDomainMasterKeyCreate(virQEMUDriverPtr driver,
+ virDomainObjPtr vm);
void qemuDomainMasterKeyRemove(qemuDomainObjPrivatePtr priv);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index b1e270ff235e..787d78670dae 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5218,7 +5218,7 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
goto cleanup;
VIR_DEBUG("Create domain masterKey");
- if (qemuDomainMasterKeyCreate(priv) < 0)
+ if (qemuDomainMasterKeyCreate(driver, vm) < 0)
goto cleanup;
ret = 0;
--
2.8.1
8 years, 7 months
[libvirt] [RFC 0/6] Probe and expose GIC capabilities
by Andrea Bolognani
This series implements support for asking QEMU what GIC versions can
be used for guests, eg:
<features>
<gic version='2'/>
</features>
and exposing such information to users via domain capabilities.
QEMU patches that implement the query-gic-capabilities QMP command:
https://lists.gnu.org/archive/html/qemu-devel/2016-03/msg04465.html
Cheers.
Andrea Bolognani (6):
conf: Get rid of virDomainCapsDevice
qemu: Probe GIC capabilities
schema: Validate GIC capabilities
conf: Expose GIC capabilities
qemu: Fill in GIC capabilities
qemu: Cache GIC capabilities
docs/schemas/domaincaps.rng | 18 +++
src/conf/domain_capabilities.c | 26 +++-
src/conf/domain_capabilities.h | 24 ++--
src/qemu/qemu_capabilities.c | 157 ++++++++++++++++++++-
src/qemu/qemu_monitor.c | 10 ++
src/qemu/qemu_monitor.h | 4 +
src/qemu/qemu_monitor_json.c | 90 ++++++++++++
src/qemu/qemu_monitor_json.h | 4 +
src/util/virgic.h | 13 ++
tests/domaincapsschemadata/domaincaps-basic.xml | 3 +
tests/domaincapsschemadata/domaincaps-full.xml | 3 +
.../domaincaps-qemu_1.6.50-1.xml | 3 +
tests/domaincapstest.c | 8 +-
13 files changed, 341 insertions(+), 22 deletions(-)
--
2.5.5
8 years, 7 months
[libvirt] [PATCH] virDomain{Get, Set}PerfEvents: Tweak documentation
by Michal Privoznik
These API already support VIR_DOMAIN_AFFECT_* flags. But the
documentation does not mention it. Eww.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt-domain.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 3e144b6..4f473c9 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -9695,11 +9695,13 @@ virDomainOpenChannel(virDomainPtr dom,
* @domain: a domain object
* @params: where to store perf events setting
* @nparams: number of items in @params
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virDomainModificationImpact
*
- * Get all perf events setting. Possible fields returned in @params are
- * defined by VIR_DOMAIN_PERF_* macros and new fields will likely be
- * introduced in the future.
+ * Get all Linux perf events setting. Possible fields returned in
+ * @params are defined by VIR_PERF_EVENT_* macros and new fields
+ * will likely be introduced in the future.
+ *
+ * Linux perf events are performance analyzing tool in Linux.
*
* Returns -1 in case of failure, 0 in case of success.
*/
@@ -9743,9 +9745,13 @@ int virDomainGetPerfEvents(virDomainPtr domain,
* @params: pointer to perf events parameter object
* @nparams: number of perf event parameters (this value can be the same
* less than the number of parameters supported)
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virDomainModificationImpact
*
- * Enable or disable the particular list of perf events you care about.
+ * Enable or disable the particular list of Linux perf events you
+ * care about. The @params argument should contain any subset of
+ * VIR_PERF_EVENT_ macros.
+ *
+ * Linux perf events are performance analyzing tool in Linux.
*
* Returns -1 in case of error, 0 in case of success.
*/
--
2.7.3
8 years, 7 months
[libvirt] [PATCH v4 00/11] Introduce worker tuning APIs
by Erik Skultety
since v3:
- fixed some indentation problem in 10/11
- for some reason daemon-side APIs did not follow our function signature
conventions, e.g. if the function name starts with virAdmServer (adminServer
for server-side version), it means that first argument is going to be
virAdmServerPtr (virNetServerPtr for server side), etc., but for some reason, I
named the server-side version adminDaemon, while passing virNetServerPtr as the
first argument
- fixed a bug when setting parameters would return error stating that
minWorkers cannot be larger than maxWorkers for configuration:
maxWorkers = 14 and minWorkers = 13
- replaced srv-workertune command with two commands srv-threadpool-info and
srv-threadpool-set, since it's much easier to extend the set of options for
each command separately than to do some black magic to determine which options
make the command behave as a getter and which ones make it behave as a setter
since v2:
- all getters are now protected by threadpool mutex to prevent torn reads in
concurrent execution
- some checks in adminDispatchServerGetThreadpoolParameters were redundant,
thus were optimizes out
- fixed memory leak in adminDispatchServerGetThreadpoolParameters when
allocating a newlist although typed params serialization already does that
- fixed some cosmetic issues like exporting a function prototype one patch
earlier than it should actually be introduced - a mistake that got there by
interactive rebase
Erik Skultety (11):
po: Fix record ordering in POTFILES.in
libvirt-host: Move virTypedParam* to libvirt-common
admin: Enable usage of typed parameters
util: Refactor thread creation by introducing virThreadPoolExpand
util: Report system error when virThreadCreateFull fails
util: Use a mutex when retrieving threadpool data
util: Add more getters to threadpool parameters
admin: Prepare admin protocol for future worker related procedures
admin: Introduce virAdmServerGethreadPoolParameters
admin: Introduce virAdmServerSetThreadPoolParameters
virt-admin: Introduce srv-threadpool-info and srv-threadpool-set
commands
cfg.mk | 2 +-
daemon/admin.c | 88 +++++++++++++
daemon/admin_server.c | 110 ++++++++++++++++
daemon/admin_server.h | 11 ++
include/libvirt/libvirt-admin.h | 71 +++++++++++
include/libvirt/libvirt-common.h.in | 185 +++++++++++++++++++++++++++
include/libvirt/libvirt-host.h | 186 ----------------------------
po/POTFILES.in | 4 +-
src/admin/admin_protocol.x | 54 +++++++-
src/admin/admin_remote.c | 77 ++++++++++++
src/admin_protocol-structs | 45 +++++++
src/libvirt-admin.c | 83 +++++++++++++
src/libvirt_admin_private.syms | 3 +
src/libvirt_admin_public.syms | 2 +
src/libvirt_private.syms | 4 +
src/rpc/virnetserver.c | 37 ++++++
src/rpc/virnetserver.h | 13 ++
src/util/virthreadpool.c | 241 ++++++++++++++++++++++++++----------
src/util/virthreadpool.h | 8 ++
tools/virt-admin.c | 185 +++++++++++++++++++++++++++
20 files changed, 1152 insertions(+), 257 deletions(-)
--
2.4.11
8 years, 7 months