Signed-off-by: Dmitry Guryanov <dguryanov(a)parallels.com>
---
src/pvs/pvs_driver.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/pvs/pvs_driver.h | 1 +
src/pvs/pvs_utils.c | 18 ++++++
3 files changed, 167 insertions(+), 0 deletions(-)
diff --git a/src/pvs/pvs_driver.c b/src/pvs/pvs_driver.c
index 7a8f99e..d2e0762 100644
--- a/src/pvs/pvs_driver.c
+++ b/src/pvs/pvs_driver.c
@@ -60,6 +60,11 @@
void pvsFreeDomObj(void *p);
static virCapsPtr pvsBuildCapabilities(void);
static int pvsClose(virConnectPtr conn);
+int pvsPause(virDomainObjPtr privdom);
+int pvsResume(virDomainObjPtr privdom);
+int pvsStart(virDomainObjPtr privdom);
+int pvsKill(virDomainObjPtr privdom);
+int pvsStop(virDomainObjPtr privdom);
static void
pvsDriverLock(pvsConnPtr driver)
@@ -87,6 +92,12 @@ pvsFreeDomObj(void *p)
VIR_FREE(pdom);
};
+static void
+pvsDomainEventQueue(pvsConnPtr driver, virDomainEventPtr event)
+{
+ virDomainEventStateQueue(driver->domainEventState, event);
+}
+
static virCapsPtr
pvsBuildCapabilities(void)
{
@@ -747,6 +758,138 @@ pvsDomainGetAutostart(virDomainPtr domain, int *autostart)
return ret;
}
+typedef int (*pvsChangeState) (virDomainObjPtr privdom);
+#define PVS_UUID(x) (((pvsDomObjPtr)(x->privateData))->uuid)
+
+static int
+pvsDomainChangeState(virDomainPtr domain,
+ virDomainState req_state, const char * req_state_name,
+ pvsChangeState chstate,
+ virDomainState new_state, int reason,
+ int event_type, int event_detail)
+{
+ pvsConnPtr privconn = domain->conn->privateData;
+ virDomainObjPtr privdom;
+ virDomainEventPtr event = NULL;
+ int state;
+ int ret = -1;
+
+ pvsDriverLock(privconn);
+ privdom = virDomainFindByName(&privconn->domains, domain->name);
+ pvsDriverUnlock(privconn);
+
+ if (privdom == NULL) {
+ pvsError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto cleanup;
+ }
+
+ state = virDomainObjGetState(privdom, NULL);
+ if (state != req_state) {
+ pvsError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not %s"),
+ privdom->def->name, req_state_name);
+ goto cleanup;
+ }
+
+ if (chstate(privdom))
+ goto cleanup;
+
+ virDomainObjSetState(privdom, new_state, reason);
+
+ event = virDomainEventNewFromObj(privdom, event_type, event_detail);
+ ret = 0;
+
+ cleanup:
+ if (privdom)
+ virDomainObjUnlock(privdom);
+
+ if (event) {
+ pvsDriverLock(privconn);
+ pvsDomainEventQueue(privconn, event);
+ pvsDriverUnlock(privconn);
+ }
+ return ret;
+}
+
+int pvsPause(virDomainObjPtr privdom)
+{
+ return pvsCmdRun(PRLCTL, "pause", PVS_UUID(privdom), NULL);
+}
+
+static int
+pvsPauseDomain(virDomainPtr domain)
+{
+ return pvsDomainChangeState(domain,
+ VIR_DOMAIN_RUNNING, "running",
+ pvsPause,
+ VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
+}
+
+int pvsResume(virDomainObjPtr privdom)
+{
+ return pvsCmdRun(PRLCTL, "resume", PVS_UUID(privdom), NULL);
+}
+
+static int
+pvsResumeDomain(virDomainPtr domain)
+{
+ return pvsDomainChangeState(domain,
+ VIR_DOMAIN_PAUSED, "paused",
+ pvsResume,
+ VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED,
+ VIR_DOMAIN_EVENT_RESUMED,
+ VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
+}
+
+int pvsStart(virDomainObjPtr privdom)
+{
+ return pvsCmdRun(PRLCTL, "start", PVS_UUID(privdom), NULL);
+}
+
+static int
+pvsDomainCreate(virDomainPtr domain)
+{
+ return pvsDomainChangeState(domain,
+ VIR_DOMAIN_SHUTOFF, "stopped",
+ pvsStart,
+ VIR_DOMAIN_RUNNING, VIR_DOMAIN_EVENT_STARTED_BOOTED,
+ VIR_DOMAIN_EVENT_STARTED,
+ VIR_DOMAIN_EVENT_STARTED_BOOTED);
+}
+
+int pvsKill(virDomainObjPtr privdom)
+{
+ return pvsCmdRun(PRLCTL, "stop", PVS_UUID(privdom), "--kill",
NULL);
+}
+
+static int
+pvsDestroyDomain(virDomainPtr domain)
+{
+ return pvsDomainChangeState(domain,
+ VIR_DOMAIN_RUNNING, "running",
+ pvsKill,
+ VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
+}
+
+int pvsStop(virDomainObjPtr privdom)
+{
+ return pvsCmdRun(PRLCTL, "stop", PVS_UUID(privdom), NULL);
+}
+
+static int
+pvsShutdownDomain(virDomainPtr domain)
+{
+ return pvsDomainChangeState(domain,
+ VIR_DOMAIN_RUNNING, "running",
+ pvsStop,
+ VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
+}
+
static virDriver pvsDriver = {
.no = VIR_DRV_PVS,
.name = "PVS",
@@ -769,6 +912,11 @@ static virDriver pvsDriver = {
.domainGetXMLDesc = pvsDomainGetXMLDesc, /* 0.9.12 */
.domainIsPersistent = pvsDomainIsPersistent, /* 0.9.12 */
.domainGetAutostart = pvsDomainGetAutostart, /* 0.9.12 */
+ .domainSuspend = pvsPauseDomain, /* 0.9.12 */
+ .domainResume = pvsResumeDomain, /* 0.9.12 */
+ .domainDestroy = pvsDestroyDomain, /* 0.9.12 */
+ .domainShutdown = pvsShutdownDomain, /* 0.9.12 */
+ .domainCreate = pvsDomainCreate, /* 0.9.12 */
};
/**
diff --git a/src/pvs/pvs_driver.h b/src/pvs/pvs_driver.h
index e0513ae..8c2d02b 100644
--- a/src/pvs/pvs_driver.h
+++ b/src/pvs/pvs_driver.h
@@ -61,5 +61,6 @@ typedef struct _pvsConn *pvsConnPtr;
int pvsRegister(void);
virJSONValuePtr pvsParseOutput(const char *binary, ...);
+int pvsCmdRun(const char *binary, ...);
#endif
diff --git a/src/pvs/pvs_utils.c b/src/pvs/pvs_utils.c
index 5d7411c..016317a 100644
--- a/src/pvs/pvs_utils.c
+++ b/src/pvs/pvs_utils.c
@@ -99,3 +99,21 @@ pvsParseOutput(const char *binary, ...)
return jobj;
}
+
+/*
+ * Run prlctl command and check for errors
+ *
+ * Return value is 0 in case of success, else - -1
+ */
+int
+pvsCmdRun(const char *binary, ...)
+{
+ int ret;
+ va_list list;
+
+ va_start(list, binary);
+ ret = pvsDoCmdRun(NULL, binary, list);
+ va_end(list);
+
+ return ret;
+}
--
1.7.1