Compare commits

..

10 Commits

Author SHA1 Message Date
645b525ad7 Bump version to 0.9.51 2022-07-25 23:25:41 -04:00
ec559aec0d Remove pvc-flush service
This service caused more headaches than it was worth, so remove it.

The original goal was to cleanly flush nodes on shutdown and unflush
them on startup, but this is tightly controlled by Ansible playbooks at
this point, and this is something best left to the Administrator and
their particular situation anyways.
2022-07-25 23:21:34 -04:00
71ffd5a191 Add confirmation to disable command 2022-07-21 16:43:37 -04:00
2739c27299 Remove faulty literal_eval 2022-07-18 13:35:15 -04:00
56129a3636 Fix bad changelog entries 2022-07-06 16:57:55 -04:00
932b3c55a3 Bump version to 0.9.50 2022-07-06 16:01:14 -04:00
92e2ff7449 Fix bug with space-containing detect strings 2022-07-06 15:58:57 -04:00
d8d3feee22 Add selector help and adjust flag name
1. Add documentation on the node selector flags. In the API, reference
the daemon configuration manual which now includes details in this
section; in the CLI, provide the help in "pvc vm define" in detail and
then reference that command's help in the other commands that use this
field.

2. Ensure the naming is consistent in the CLI, using the flag name
"--node-selector" everywhere (was "--selector" for "pvc vm" commands and
"--node-selector" for "pvc provisioner" commands).
2022-06-10 02:42:06 -04:00
b1357cafdb Add memfree to selector and use proper defaults 2022-06-10 02:03:12 -04:00
f8cdcb30ba Add migration selector via free memory
Closes #152
2022-05-18 03:47:16 -04:00
17 changed files with 146 additions and 66 deletions

View File

@ -1 +1 @@
0.9.49
0.9.51

View File

@ -1,5 +1,16 @@
## PVC Changelog
###### [v0.9.51](https://github.com/parallelvirtualcluster/pvc/releases/tag/v0.9.51)
* [CLI Client] Fixes a faulty literal_eval when viewing task status
* [CLI Client] Adds a confirmation flag to the vm disable command
* [Node Daemon] Removes the pvc-flush service
###### [v0.9.50](https://github.com/parallelvirtualcluster/pvc/releases/tag/v0.9.50)
* [Node Daemon/API/CLI] Adds free memory node selector
* [Node Daemon] Fixes bug sending space-containing detect disk strings
###### [v0.9.49](https://github.com/parallelvirtualcluster/pvc/releases/tag/v0.9.49)
* [Node Daemon] Fixes bugs with OSD stat population on creation

View File

@ -25,7 +25,7 @@ import yaml
from distutils.util import strtobool as dustrtobool
# Daemon version
version = "0.9.49"
version = "0.9.51"
# API version
API_VERSION = 1.0

View File

@ -1002,7 +1002,7 @@ class API_VM_Root(Resource):
type: string
node_selector:
type: string
description: The selector used to determine candidate nodes during migration
description: The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference
node_autostart:
type: boolean
description: Whether to autostart the VM when its node returns to ready domain state
@ -1252,7 +1252,7 @@ class API_VM_Root(Resource):
{"name": "node"},
{
"name": "selector",
"choices": ("mem", "vcpus", "load", "vms", "none"),
"choices": ("mem", "memfree", "vcpus", "load", "vms", "none"),
"helptext": "A valid selector must be specified",
},
{"name": "autostart"},
@ -1297,13 +1297,15 @@ class API_VM_Root(Resource):
name: selector
type: string
required: false
description: The selector used to determine candidate nodes during migration
default: mem
description: The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference
default: none
enum:
- mem
- memfree
- vcpus
- load
- vms
- none (cluster default)
- in: query
name: autostart
type: boolean
@ -1397,7 +1399,7 @@ class API_VM_Element(Resource):
{"name": "node"},
{
"name": "selector",
"choices": ("mem", "vcpus", "load", "vms", "none"),
"choices": ("mem", "memfree", "vcpus", "load", "vms", "none"),
"helptext": "A valid selector must be specified",
},
{"name": "autostart"},
@ -1444,10 +1446,11 @@ class API_VM_Element(Resource):
name: selector
type: string
required: false
description: The selector used to determine candidate nodes during migration
default: mem
description: The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference
default: none
enum:
- mem
- memfree
- vcpus
- load
- vms
@ -1626,7 +1629,7 @@ class API_VM_Metadata(Resource):
type: string
node_selector:
type: string
description: The selector used to determine candidate nodes during migration
description: The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference
node_autostart:
type: string
description: Whether to autostart the VM when its node returns to ready domain state
@ -1646,7 +1649,7 @@ class API_VM_Metadata(Resource):
{"name": "limit"},
{
"name": "selector",
"choices": ("mem", "vcpus", "load", "vms", "none"),
"choices": ("mem", "memfree", "vcpus", "load", "vms", "none"),
"helptext": "A valid selector must be specified",
},
{"name": "autostart"},
@ -1675,12 +1678,14 @@ class API_VM_Metadata(Resource):
name: selector
type: string
required: false
description: The selector used to determine candidate nodes during migration
description: The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference
enum:
- mem
- memfree
- vcpus
- load
- vms
- none (cluster default)
- in: query
name: autostart
type: boolean

View File

@ -23,7 +23,6 @@ from requests_toolbelt.multipart.encoder import (
MultipartEncoder,
MultipartEncoderMonitor,
)
from ast import literal_eval
import pvc.cli_lib.ansiprint as ansiprint
from pvc.cli_lib.common import UploadProgressBar, call_api
@ -793,10 +792,10 @@ def task_status(config, task_id=None, is_watching=False):
task["type"] = task_type
task["worker"] = task_host
task["id"] = task_job.get("id")
task_args = literal_eval(task_job.get("args"))
task_args = task_job.get("args")
task["vm_name"] = task_args[0]
task["vm_profile"] = task_args[1]
task_kwargs = literal_eval(task_job.get("kwargs"))
task_kwargs = task_job.get("kwargs")
task["vm_define"] = str(bool(task_kwargs["define_vm"]))
task["vm_start"] = str(bool(task_kwargs["start_vm"]))
task_data.append(task)

View File

@ -803,11 +803,11 @@ def cli_vm():
)
@click.option(
"-s",
"--selector",
"--node-selector",
"node_selector",
default="mem",
default="none",
show_default=True,
type=click.Choice(["mem", "load", "vcpus", "vms", "none"]),
type=click.Choice(["mem", "memfree", "load", "vcpus", "vms", "none"]),
help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.',
)
@click.option(
@ -857,6 +857,18 @@ def vm_define(
):
"""
Define a new virtual machine from Libvirt XML configuration file VMCONFIG.
The target node selector ("--node-selector"/"-s") can be "none" to use the cluster default, or one of the following values:
* "mem": choose the node with the least provisioned VM memory
* "memfree": choose the node with the most (real) free memory
* "vcpus": choose the node with the least allocated VM vCPUs
* "load": choose the node with the lowest current load average
* "vms": choose the node with the least number of provisioned VMs
For most clusters, "mem" should be sufficient, but others may be used based on the cluster workload and available resources. The following caveats should be considered:
* "mem" looks at the provisioned memory, not the allocated memory; thus, stopped or disabled VMs are counted towards a node's memory for this selector, even though their memory is not actively in use.
* "memfree" looks at the free memory of the node in general, ignoring the amount provisioned to VMs; if any VM's internal memory usage changes, this value would be affected. This might be preferable to "mem" on clusters with very high memory utilization versus total capacity or if many VMs are stopped/disabled.
* "load" looks at the system load of the node in general, ignoring load in any particular VMs; if any VM's CPU usage changes, this value would be affected. This might be preferable on clusters with some very CPU intensive VMs.
"""
# Open the XML file
@ -898,11 +910,11 @@ def vm_define(
)
@click.option(
"-s",
"--selector",
"--node-selector",
"node_selector",
default=None,
show_default=False,
type=click.Choice(["mem", "load", "vcpus", "vms", "none"]),
type=click.Choice(["mem", "memfree", "load", "vcpus", "vms", "none"]),
help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.',
)
@click.option(
@ -942,6 +954,8 @@ def vm_meta(
):
"""
Modify the PVC metadata of existing virtual machine DOMAIN. At least one option to update must be specified. DOMAIN may be a UUID or name.
For details on the "--node-selector"/"-s" values, please see help for the command "pvc vm define".
"""
if (
@ -1343,15 +1357,31 @@ def vm_stop(domain, confirm_flag):
default=False,
help="Forcibly stop the VM instead of waiting for shutdown.",
)
@click.option(
"-y",
"--yes",
"confirm_flag",
is_flag=True,
default=False,
help="Confirm the disable",
)
@cluster_req
def vm_disable(domain, force):
def vm_disable(domain, force_flag, confirm_flag):
"""
Shut down virtual machine DOMAIN and mark it as disabled. DOMAIN may be a UUID or name.
Disabled VMs will not be counted towards a degraded cluster health status, unlike stopped VMs. Use this option for a VM that will remain off for an extended period.
"""
retcode, retmsg = pvc_vm.vm_state(config, domain, "disable", force=force)
if not confirm_flag and not config["unsafe"]:
try:
click.confirm(
"Disable VM {}".format(domain), prompt_suffix="? ", abort=True
)
except Exception:
exit(0)
retcode, retmsg = pvc_vm.vm_state(config, domain, "disable", force=force_flag)
cleanup(retcode, retmsg)
@ -4102,7 +4132,9 @@ def provisioner_template_system_list(limit):
@click.option(
"--node-selector",
"node_selector",
type=click.Choice(["mem", "vcpus", "vms", "load", "none"], case_sensitive=False),
type=click.Choice(
["mem", "memfree", "vcpus", "vms", "load", "none"], case_sensitive=False
),
default="none",
help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.',
)
@ -4135,6 +4167,8 @@ def provisioner_template_system_add(
):
"""
Add a new system template NAME to the PVC cluster provisioner.
For details on the possible "--node-selector" values, please see help for the command "pvc vm define".
"""
params = dict()
params["name"] = name
@ -4194,7 +4228,9 @@ def provisioner_template_system_add(
@click.option(
"--node-selector",
"node_selector",
type=click.Choice(["mem", "vcpus", "vms", "load", "none"], case_sensitive=False),
type=click.Choice(
["mem", "memfree", "vcpus", "vms", "load", "none"], case_sensitive=False
),
help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.',
)
@click.option(
@ -4226,6 +4262,8 @@ def provisioner_template_system_modify(
):
"""
Add a new system template NAME to the PVC cluster provisioner.
For details on the possible "--node-selector" values, please see help for the command "pvc vm define".
"""
params = dict()
params["vcpus"] = vcpus

View File

@ -2,7 +2,7 @@ from setuptools import setup
setup(
name="pvc",
version="0.9.49",
version="0.9.51",
packages=["pvc", "pvc.cli_lib"],
install_requires=[
"Click",

View File

@ -639,6 +639,8 @@ def findTargetNode(zkhandler, dom_uuid):
# Execute the search
if search_field == "mem":
return findTargetNodeMem(zkhandler, node_limit, dom_uuid)
if search_field == "memfree":
return findTargetNodeMemFree(zkhandler, node_limit, dom_uuid)
if search_field == "load":
return findTargetNodeLoad(zkhandler, node_limit, dom_uuid)
if search_field == "vcpus":
@ -677,7 +679,7 @@ def getNodes(zkhandler, node_limit, dom_uuid):
#
# via free memory (relative to allocated memory)
# via provisioned memory
#
def findTargetNodeMem(zkhandler, node_limit, dom_uuid):
most_provfree = 0
@ -698,6 +700,24 @@ def findTargetNodeMem(zkhandler, node_limit, dom_uuid):
return target_node
#
# via free memory
#
def findTargetNodeMemFree(zkhandler, node_limit, dom_uuid):
most_memfree = 0
target_node = None
node_list = getNodes(zkhandler, node_limit, dom_uuid)
for node in node_list:
memfree = int(zkhandler.read(("node.memory.free", node)))
if memfree > most_memfree:
most_memfree = memfree
target_node = node
return target_node
#
# via load average
#

15
debian/changelog vendored
View File

@ -1,3 +1,18 @@
pvc (0.9.51-0) unstable; urgency=high
* [CLI Client] Fixes a faulty literal_eval when viewing task status
* [CLI Client] Adds a confirmation flag to the vm disable command
* [Node Daemon] Removes the pvc-flush service
-- Joshua M. Boniface <joshua@boniface.me> Mon, 25 Jul 2022 23:25:41 -0400
pvc (0.9.50-0) unstable; urgency=high
* [Node Daemon/API/CLI] Adds free memory node selector
* [Node Daemon] Fixes bug sending space-containing detect disk strings
-- Joshua M. Boniface <joshua@boniface.me> Wed, 06 Jul 2022 16:01:14 -0400
pvc (0.9.49-0) unstable; urgency=high
* [Node Daemon] Fixes bugs with OSD stat population on creation

View File

@ -3,5 +3,4 @@ node-daemon/pvcnoded.sample.yaml etc/pvc
node-daemon/pvcnoded usr/share/pvc
node-daemon/pvcnoded.service lib/systemd/system
node-daemon/pvc.target lib/systemd/system
node-daemon/pvc-flush.service lib/systemd/system
node-daemon/monitoring usr/share/pvc

View File

@ -7,11 +7,6 @@ systemctl daemon-reload
systemctl enable /lib/systemd/system/pvcnoded.service
systemctl enable /lib/systemd/system/pvc.target
# Inform administrator of the autoflush daemon if it is not enabled
if ! systemctl is-active --quiet pvc-flush.service; then
echo "NOTE: The PVC autoflush daemon (pvc-flush.service) is not enabled by default; enable it to perform automatic flush/unflush actions on host shutdown/startup."
fi
# Inform administrator of the service restart/startup not occurring automatically
if systemctl is-active --quiet pvcnoded.service; then
echo "NOTE: The PVC node daemon (pvcnoded.service) has not been restarted; this is up to the administrator."

View File

@ -353,7 +353,19 @@ The password for the PVC node daemon to log in to the IPMI interface.
* *required*
The selector algorithm to use when migrating hosts away from the node. Valid `selector` values are: `mem`: the node with the least allocated VM memory; `vcpus`: the node with the least allocated VM vCPUs; `load`: the node with the least current load average; `vms`: the node with the least number of provisioned VMs.
The default selector algorithm to use when migrating VMs away from a node; individual VMs can override this default.
Valid `target_selector` values are:
* `mem`: choose the node with the least provisioned VM memory
* `memfree`: choose the node with the most (real) free memory
* `vcpus`: choose the node with the least allocated VM vCPUs
* `load`: choose the node with the lowest current load average
* `vms`: choose the node with the least number of provisioned VMs
For most clusters, `mem` should be sufficient, but others may be used based on the cluster workload and available resources. The following caveats should be considered:
* `mem` looks at the provisioned memory, not the allocated memory; thus, stopped or disabled VMs are counted towards a node's memory for this selector, even though their memory is not actively in use.
* `memfree` looks at the free memory of the node in general, ignoring the amount provisioned to VMs; if any VM's internal memory usage changes, this value would be affected. This might be preferable to `mem` on clusters with very high memory utilization versus total capacity or if many VMs are stopped/disabled.
* `load` looks at the system load of the node in general, ignoring load in any particular VMs; if any VM's CPU usage changes, this value would be affected. This might be preferable on clusters with some very CPU intensive VMs.
#### `system` → `configuration` → `directories` → `dynamic_directory`

View File

@ -192,7 +192,7 @@
"type": "array"
},
"node_selector": {
"description": "The selector used to determine candidate nodes during migration",
"description": "The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference",
"type": "string"
}
},
@ -1414,7 +1414,7 @@
"type": "array"
},
"node_selector": {
"description": "The selector used to determine candidate nodes during migration",
"description": "The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference",
"type": "string"
},
"profile": {
@ -6173,13 +6173,15 @@
"type": "string"
},
{
"default": "mem",
"description": "The selector used to determine candidate nodes during migration",
"default": "none",
"description": "The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference",
"enum": [
"mem",
"memfree",
"vcpus",
"load",
"vms"
"vms",
"none (cluster default)"
],
"in": "query",
"name": "selector",
@ -6330,10 +6332,11 @@
"type": "string"
},
{
"default": "mem",
"description": "The selector used to determine candidate nodes during migration",
"default": "none",
"description": "The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference",
"enum": [
"mem",
"memfree",
"vcpus",
"load",
"vms",
@ -6591,12 +6594,14 @@
"type": "string"
},
{
"description": "The selector used to determine candidate nodes during migration",
"description": "The selector used to determine candidate nodes during migration; see 'target_selector' in the node daemon configuration reference",
"enum": [
"mem",
"memfree",
"vcpus",
"load",
"vms"
"vms",
"none (cluster default)"
],
"in": "query",
"name": "selector",

View File

@ -1,20 +0,0 @@
# Parallel Virtual Cluster autoflush daemon
[Unit]
Description = Parallel Virtual Cluster autoflush daemon
After = pvcnoded.service pvcapid.service zookeeper.service libvirtd.service ssh.service ceph.target network-online.target
Wants = pvcnoded.service
PartOf = pvc.target
[Service]
Type = oneshot
RemainAfterExit = true
WorkingDirectory = /usr/share/pvc
TimeoutSec = 30min
ExecStartPre = /bin/sleep 30
ExecStart = /usr/bin/pvc -c local node unflush --wait
ExecStop = /usr/bin/pvc -c local node flush --wait
ExecStopPost = /bin/sleep 5
[Install]
WantedBy = pvc.target

View File

@ -122,7 +122,7 @@ pvc:
pass: Passw0rd
# migration: Migration option configuration
migration:
# target_selector: Criteria to select the ideal migration target, options: mem, load, vcpus, vms
# target_selector: Criteria to select the ideal migration target, options: mem, memfree, load, vcpus, vms
target_selector: mem
# configuration: Local system configurations
configuration:

View File

@ -48,7 +48,7 @@ import re
import json
# Daemon version
version = "0.9.49"
version = "0.9.51"
##########################################################

View File

@ -1239,8 +1239,9 @@ class CephSnapshotInstance(object):
# Primary command function
# This command pipe is only used for OSD adds and removes
def ceph_command(zkhandler, logger, this_node, data, d_osd):
# Get the command and args
command, args = data.split()
# Get the command and args; the * + join ensures arguments with spaces (e.g. detect strings) are recombined right
command, *args = data.split()
args = " ".join(args)
# Adding a new OSD
if command == "osd_add":