Revision 72cd5493 lib/ht.py
b/lib/ht.py | ||
---|---|---|
23 | 23 |
|
24 | 24 |
import re |
25 | 25 |
import operator |
26 |
import ipaddr |
|
26 | 27 |
|
27 | 28 |
from ganeti import compat |
28 | 29 |
from ganeti import utils |
29 | 30 |
from ganeti import constants |
31 |
from ganeti import objects |
|
30 | 32 |
|
31 | 33 |
|
32 | 34 |
_PAREN_RE = re.compile("^[a-zA-Z0-9_-]+$") |
... | ... | |
359 | 361 |
#: Maybe a list (list or None) |
360 | 362 |
TMaybeList = TMaybe(TList) |
361 | 363 |
|
364 |
|
|
365 |
#: a non-negative number (value > 0) |
|
366 |
# val_type should be TInt, TDouble (== TFloat), or TNumber |
|
367 |
def TNonNegative(val_type): |
|
368 |
return WithDesc("EqualOrGreaterThanZero")(TAnd(val_type, lambda v: v >= 0)) |
|
369 |
|
|
370 |
|
|
371 |
#: a positive number (value >= 0) |
|
372 |
# val_type should be TInt, TDouble (== TFloat), or TNumber |
|
373 |
def TPositive(val_type): |
|
374 |
return WithDesc("GreaterThanZero")(TAnd(val_type, lambda v: v > 0)) |
|
375 |
|
|
376 |
|
|
362 | 377 |
#: a non-negative integer (value >= 0) |
363 |
TNonNegativeInt = \ |
|
364 |
TAnd(TInt, WithDesc("EqualOrGreaterThanZero")(lambda v: v >= 0)) |
|
378 |
TNonNegativeInt = TNonNegative(TInt) |
|
365 | 379 |
|
366 | 380 |
#: a positive integer (value > 0) |
367 |
TPositiveInt = \ |
|
368 |
TAnd(TInt, WithDesc("GreaterThanZero")(lambda v: v > 0)) |
|
381 |
TPositiveInt = TPositive(TInt) |
|
369 | 382 |
|
370 | 383 |
#: a maybe positive integer (positive integer or None) |
371 | 384 |
TMaybePositiveInt = TMaybe(TPositiveInt) |
... | ... | |
383 | 396 |
TRegex(re.compile("^%s$" % |
384 | 397 |
constants.JOB_ID_TEMPLATE)))) |
385 | 398 |
|
399 |
#: Double (== Float) |
|
400 |
TDouble = TFloat |
|
401 |
|
|
386 | 402 |
#: Number |
387 | 403 |
TNumber = TOr(TInt, TFloat) |
388 | 404 |
|
... | ... | |
415 | 431 |
TMaybeListOf = lambda item_type: TMaybe(TListOf(item_type)) |
416 | 432 |
|
417 | 433 |
|
434 |
def TTupleOf(*val_types): |
|
435 |
"""Checks if a given value is a list with the proper size and its |
|
436 |
elements match the given types. |
|
437 |
|
|
438 |
""" |
|
439 |
desc = WithDesc("Tuple of %s" % (Parens(val_types), )) |
|
440 |
return desc(TAnd(TIsLength(len(val_types)), TItems(val_types))) |
|
441 |
|
|
442 |
|
|
443 |
def TSetOf(val_type): |
|
444 |
"""Checks if a given value is a list with all elements of the same |
|
445 |
type and eliminates duplicated elements. |
|
446 |
|
|
447 |
""" |
|
448 |
desc = WithDesc("Set of %s" % (Parens(val_type), )) |
|
449 |
return desc(lambda st: TListOf(val_type)(list(set(st)))) |
|
450 |
|
|
451 |
|
|
418 | 452 |
def TDictOf(key_type, val_type): |
419 | 453 |
"""Checks a dict type for the type of its key/values. |
420 | 454 |
|
... | ... | |
497 | 531 |
|
498 | 532 |
return desc(lambda value: compat.all(check(i) |
499 | 533 |
for (check, i) in zip(items, value))) |
534 |
|
|
535 |
|
|
536 |
TAllocPolicy = TElemOf(constants.VALID_ALLOC_POLICIES) |
|
537 |
TCVErrorCode = TElemOf(constants.CV_ALL_ECODES_STRINGS) |
|
538 |
TQueryResultCode = TElemOf(constants.RS_ALL) |
|
539 |
TExportTarget = TOr(TNonEmptyString, TList) |
|
540 |
TExportMode = TElemOf(constants.EXPORT_MODES) |
|
541 |
TDiskIndex = TAnd(TNonNegativeInt, lambda val: val < constants.MAX_DISKS) |
|
542 |
TReplaceDisksMode = TElemOf(constants.REPLACE_MODES) |
|
543 |
TDiskTemplate = TElemOf(constants.DISK_TEMPLATES) |
|
544 |
TNodeEvacMode = TElemOf(constants.IALLOCATOR_NEVAC_MODES) |
|
545 |
TIAllocatorTestDir = TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS) |
|
546 |
TIAllocatorMode = TElemOf(constants.VALID_IALLOCATOR_MODES) |
|
547 |
|
|
548 |
|
|
549 |
def TSetParamsMods(fn): |
|
550 |
"""Generates a check for modification lists. |
|
551 |
|
|
552 |
""" |
|
553 |
# Old format |
|
554 |
# TODO: Remove in version 2.11 including support in LUInstanceSetParams |
|
555 |
old_mod_item_fn = \ |
|
556 |
TAnd(TIsLength(2), |
|
557 |
TItems([TOr(TElemOf(constants.DDMS_VALUES), TNonNegativeInt), fn])) |
|
558 |
|
|
559 |
# New format, supporting adding/removing disks/NICs at arbitrary indices |
|
560 |
mod_item_fn = \ |
|
561 |
TAnd(TIsLength(3), TItems([ |
|
562 |
TElemOf(constants.DDMS_VALUES_WITH_MODIFY), |
|
563 |
Comment("Device index, can be negative, e.g. -1 for last disk") |
|
564 |
(TOr(TInt, TString)), |
|
565 |
fn, |
|
566 |
])) |
|
567 |
|
|
568 |
return TOr(Comment("Recommended")(TListOf(mod_item_fn)), |
|
569 |
Comment("Deprecated")(TListOf(old_mod_item_fn))) |
|
570 |
|
|
571 |
|
|
572 |
TINicParams = \ |
|
573 |
Comment("NIC parameters")(TDictOf(TElemOf(constants.INIC_PARAMS), |
|
574 |
TMaybeString)) |
|
575 |
|
|
576 |
TIDiskParams = \ |
|
577 |
Comment("Disk parameters")(TDictOf(TElemOf(constants.IDISK_PARAMS), |
|
578 |
TOr(TNonEmptyString, TInt))) |
|
579 |
|
|
580 |
THypervisor = TElemOf(constants.HYPER_TYPES) |
|
581 |
TMigrationMode = TElemOf(constants.HT_MIGRATION_MODES) |
|
582 |
TNICMode = TElemOf(constants.NIC_VALID_MODES) |
|
583 |
TInstCreateMode = TElemOf(constants.INSTANCE_CREATE_MODES) |
|
584 |
TRebootType = TElemOf(constants.REBOOT_TYPES) |
|
585 |
TFileDriver = TElemOf(constants.FILE_DRIVER) |
|
586 |
TOobCommand = TElemOf(constants.OOB_COMMANDS) |
|
587 |
TQueryTypeOp = TElemOf(constants.QR_VIA_OP) |
|
588 |
|
|
589 |
TDiskParams = \ |
|
590 |
Comment("Disk parameters")(TDictOf(TNonEmptyString, |
|
591 |
TOr(TNonEmptyString, TInt))) |
|
592 |
|
|
593 |
TDiskChanges = \ |
|
594 |
TAnd(TIsLength(2), |
|
595 |
TItems([Comment("Disk index")(TNonNegativeInt), |
|
596 |
Comment("Parameters")(TDiskParams)])) |
|
597 |
|
|
598 |
TRecreateDisksInfo = TOr(TListOf(TNonNegativeInt), TListOf(TDiskChanges)) |
|
599 |
|
|
600 |
|
|
601 |
def TStorageType(val): |
|
602 |
"""Builds a function that checks if a given value is a valid storage |
|
603 |
type. |
|
604 |
|
|
605 |
""" |
|
606 |
return (val in constants.STORAGE_TYPES) |
|
607 |
|
|
608 |
|
|
609 |
TTagKind = TElemOf(constants.VALID_TAG_TYPES) |
|
610 |
TDdmSimple = TElemOf(constants.DDMS_VALUES) |
|
611 |
TVerifyOptionalChecks = TElemOf(constants.VERIFY_OPTIONAL_CHECKS) |
|
612 |
|
|
613 |
|
|
614 |
@WithDesc("IPv4 network") |
|
615 |
def _CheckCIDRNetNotation(value): |
|
616 |
"""Ensure a given CIDR notation type is valid. |
|
617 |
|
|
618 |
""" |
|
619 |
try: |
|
620 |
ipaddr.IPv4Network(value) |
|
621 |
except ipaddr.AddressValueError: |
|
622 |
return False |
|
623 |
return True |
|
624 |
|
|
625 |
|
|
626 |
@WithDesc("IPv4 address") |
|
627 |
def _CheckCIDRAddrNotation(value): |
|
628 |
"""Ensure a given CIDR notation type is valid. |
|
629 |
|
|
630 |
""" |
|
631 |
try: |
|
632 |
ipaddr.IPv4Address(value) |
|
633 |
except ipaddr.AddressValueError: |
|
634 |
return False |
|
635 |
return True |
|
636 |
|
|
637 |
|
|
638 |
@WithDesc("IPv6 address") |
|
639 |
def _CheckCIDR6AddrNotation(value): |
|
640 |
"""Ensure a given CIDR notation type is valid. |
|
641 |
|
|
642 |
""" |
|
643 |
try: |
|
644 |
ipaddr.IPv6Address(value) |
|
645 |
except ipaddr.AddressValueError: |
|
646 |
return False |
|
647 |
return True |
|
648 |
|
|
649 |
|
|
650 |
@WithDesc("IPv6 network") |
|
651 |
def _CheckCIDR6NetNotation(value): |
|
652 |
"""Ensure a given CIDR notation type is valid. |
|
653 |
|
|
654 |
""" |
|
655 |
try: |
|
656 |
ipaddr.IPv6Network(value) |
|
657 |
except ipaddr.AddressValueError: |
|
658 |
return False |
|
659 |
return True |
|
660 |
|
|
661 |
|
|
662 |
TIPv4Address = TAnd(TString, _CheckCIDRAddrNotation) |
|
663 |
TIPv6Address = TAnd(TString, _CheckCIDR6AddrNotation) |
|
664 |
TIPv4Network = TAnd(TString, _CheckCIDRNetNotation) |
|
665 |
TIPv6Network = TAnd(TString, _CheckCIDR6NetNotation) |
|
666 |
|
|
667 |
|
|
668 |
def TObject(val_type): |
|
669 |
return TDictOf(TAny, val_type) |
|
670 |
|
|
671 |
|
|
672 |
def TObjectCheck(obj, fields_types): |
|
673 |
"""Helper to generate type checks for objects. |
|
674 |
|
|
675 |
@param obj: The object to generate type checks |
|
676 |
@param fields_types: The fields and their types as a dict |
|
677 |
@return: A ht type check function |
|
678 |
|
|
679 |
""" |
|
680 |
assert set(obj.GetAllSlots()) == set(fields_types.keys()), \ |
|
681 |
"%s != %s" % (set(obj.GetAllSlots()), set(fields_types.keys())) |
|
682 |
return TStrictDict(True, True, fields_types) |
|
683 |
|
|
684 |
|
|
685 |
TQueryFieldDef = \ |
|
686 |
TObjectCheck(objects.QueryFieldDefinition, { |
|
687 |
"name": TNonEmptyString, |
|
688 |
"title": TNonEmptyString, |
|
689 |
"kind": TElemOf(constants.QFT_ALL), |
|
690 |
"doc": TNonEmptyString |
|
691 |
}) |
|
692 |
|
|
693 |
TQueryRow = \ |
|
694 |
TListOf(TAnd(TIsLength(2), |
|
695 |
TItems([TElemOf(constants.RS_ALL), TAny]))) |
|
696 |
|
|
697 |
TQueryResult = TListOf(TQueryRow) |
|
698 |
|
|
699 |
TQueryResponse = \ |
|
700 |
TObjectCheck(objects.QueryResponse, { |
|
701 |
"fields": TListOf(TQueryFieldDef), |
|
702 |
"data": TQueryResult |
|
703 |
}) |
|
704 |
|
|
705 |
TQueryFieldsResponse = \ |
|
706 |
TObjectCheck(objects.QueryFieldsResponse, { |
|
707 |
"fields": TListOf(TQueryFieldDef) |
|
708 |
}) |
|
709 |
|
|
710 |
TJobIdListItem = \ |
|
711 |
TAnd(TIsLength(2), |
|
712 |
TItems([Comment("success")(TBool), |
|
713 |
Comment("Job ID if successful, error message" |
|
714 |
" otherwise")(TOr(TString, TJobId))])) |
|
715 |
|
|
716 |
TJobIdList = TListOf(TJobIdListItem) |
|
717 |
|
|
718 |
TJobIdListOnly = TStrictDict(True, True, { |
|
719 |
constants.JOB_IDS_KEY: Comment("List of submitted jobs")(TJobIdList) |
|
720 |
}) |
|
721 |
|
|
722 |
TInstanceMultiAllocResponse = \ |
|
723 |
TStrictDict(True, True, { |
|
724 |
constants.JOB_IDS_KEY: Comment("List of submitted jobs")(TJobIdList), |
|
725 |
ALLOCATABLE_KEY: TListOf(TNonEmptyString), |
|
726 |
FAILED_KEY: TListOf(TNonEmptyString) |
|
727 |
}) |
Also available in: Unified diff