]> git.proxmox.com Git - pve-cluster.git/blobdiff - data/PVE/DataCenterConfig.pm
buildsys: add sbuild convenience target
[pve-cluster.git] / data / PVE / DataCenterConfig.pm
index 782abea38af0867e9924602dfc8eacd7705b2de3..5f12450561f2b19fcdcc4e093deab87b1d732c06 100644 (file)
@@ -7,6 +7,26 @@ use PVE::JSONSchema qw(parse_property_string);
 use PVE::Tools;
 use PVE::Cluster;
 
+my $crs_format = {
+    ha => {
+       type => 'string',
+       enum => ['basic', 'static'],
+       optional => 1,
+       default => 'basic',
+       description => "Use this resource scheduler mode for HA.",
+       verbose_description => "Configures how the HA manager should select nodes to start or ".
+           "recover services. With 'basic', only the number of services is used, with 'static', ".
+           "static CPU and memory configuration of services is considered.",
+    },
+    'ha-rebalance-on-start' => {
+       type => 'boolean',
+       optional => 1,
+       default => 0,
+       description => "Set to use CRS for selecting a suited node when a HA services request-state"
+           ." changes from stop to start.",
+    }
+};
+
 my $migration_format = {
     type => {
        default_key => 1,
@@ -25,6 +45,20 @@ my $migration_format = {
     },
 };
 
+my $notification_format = {
+    'package-updates' => {
+       type => 'string',
+       enum => ['auto', 'always', 'never'],
+       description => "Control when the daily update job should send out notification mails.",
+       verbose_description => "Control how often the daily update job should send out notification mails:\n"
+           ."* 'auto' daily for systems with a valid subscription, as those are assumed to be "
+           ." production-ready and thus should know about pending updates.\n"
+           ."* 'always' every update, if there are new pending updates.\n"
+           ."* 'never' never send a notification for new pending updates.\n",
+       default => 'auto',
+    },
+};
+
 my $ha_format = {
     shutdown_policy => {
        type => 'string',
@@ -62,9 +96,9 @@ my $next_id_format = {
     },
     upper => {
        type => 'integer',
-       description => "Upper, inclusive boundary for free next-id API range.",
+       description => "Upper, exclusive boundary for free next-id API range.",
        min => 100,
-       max => 1000 * 1000 * 1000 - 1,
+       max => 1000 * 1000 * 1000,
        default => 1000 * 1000, # lower than the maximum on purpose
        optional => 1,
     },
@@ -107,11 +141,17 @@ my $webauthn_format = {
     id => {
        type => 'string',
        description =>
-           'Relying part ID. Must be the domain name without protocol, port or location.'
+           'Relying party ID. Must be the domain name without protocol, port or location.'
            .' Changing this *will* break existing credentials.',
        format_description => 'DOMAINNAME',
        optional => 1,
     },
+    'allow-subdomains' => {
+       type => 'boolean',
+       description => 'Whether to allow the origin to be a subdomain, rather than the exact URL.',
+       optional => 1,
+       default => 1,
+    },
 };
 
 PVE::JSONSchema::register_format('mac-prefix', \&pve_verify_mac_prefix);
@@ -125,10 +165,77 @@ sub pve_verify_mac_prefix {
     return $mac_prefix;
 }
 
+my $COLOR_RE = '[0-9a-fA-F]{6}';
+my $TAG_COLOR_OVERRIDE_RE = "(?:${PVE::JSONSchema::PVE_TAG_RE}:${COLOR_RE}(?:\:${COLOR_RE})?)";
+
+my $tag_style_format = {
+    'shape' => {
+       optional => 1,
+       type => 'string',
+       enum => ['full', 'circle', 'dense', 'none'],
+       default => 'circle',
+       description => "Tag shape for the web ui tree. 'full' draws the full tag. "
+           ."'circle' draws only a circle with the background color. "
+           ."'dense' only draws a small rectancle (useful when many tags are assigned to each guest)."
+           ."'none' disables showing the tags.",
+    },
+    'color-map' => {
+       optional => 1,
+       type => 'string',
+       pattern => "${TAG_COLOR_OVERRIDE_RE}(?:\;$TAG_COLOR_OVERRIDE_RE)*",
+       typetext => '<tag>:<hex-color>[:<hex-color-for-text>][;<tag>=...]',
+       description => "Manual color mapping for tags (semicolon separated).",
+    },
+    ordering => {
+       optional => 1,
+       type => 'string',
+       enum => ['config', 'alphabetical'],
+       default => 'alphabetical',
+       description => 'Controls the sorting of the tags in the web-interface and the API update.',
+    },
+    'case-sensitive' => {
+       type => 'boolean',
+       description => 'Controls if filtering for unique tags on update should check case-sensitive.',
+       optional => 1,
+       default => 0,
+    },
+};
+
+my $user_tag_privs_format = {
+    'user-allow' => {
+       optional => 1,
+       type => 'string',
+       enum => ['none', 'list', 'existing', 'free'],
+       default => 'free',
+       description => "Controls tag usage for users without `Sys.Modify` on `/` by either "
+           ."allowing `none`, a `list`, already `existing` or anything (`free`).",
+       verbose_description => "Controls which tags can be set or deleted on resources a user "
+           ."controls (such as guests). Users with the `Sys.Modify` privilege on `/` are always "
+           ." unrestricted. "
+           ."* 'none' no tags are usable. "
+           ."* 'list' tags from 'user-allow-list' are usable. "
+           ."* 'existing' like list, but already existing tags of resources are also usable."
+           ."* 'free' no tag restrictions.",
+    },
+    'user-allow-list' => {
+       optional => 1,
+       type => 'string',
+       pattern => "${PVE::JSONSchema::PVE_TAG_RE}(?:\;${PVE::JSONSchema::PVE_TAG_RE})*",
+       typetext => "<tag>[;<tag>...]",
+       description => "List of tags users are allowed to set and delete (semicolon separated) "
+           ."for 'user-allow' values 'list' and 'existing'.",
+    },
+};
+
 my $datacenter_schema = {
     type => "object",
     additionalProperties => 0,
     properties => {
+       crs => {
+           optional => 1,
+           type => 'string', format => $crs_format,
+           description => "Cluster resource scheduling settings.",
+       },
        keyboard => {
            optional => 1,
            type => 'string',
@@ -230,6 +337,11 @@ my $datacenter_schema = {
            format => 'mac-prefix',
            description => 'Prefix for autogenerated MAC addresses.',
        },
+       notify => {
+           optional => 1,
+           type => 'string', format => $notification_format,
+           description => "Cluster-wide notification settings.",
+       },
        bwlimit => PVE::JSONSchema::get_standard_option('bwlimit'),
        u2f => {
            optional => 1,
@@ -250,6 +362,26 @@ my $datacenter_schema = {
            maxLength => 64 * 1024,
            optional => 1,
        },
+       'tag-style' => {
+           optional => 1,
+           type => 'string',
+           description => "Tag style options.",
+           format => $tag_style_format,
+       },
+       'user-tag-access' => {
+           optional => 1,
+           type => 'string',
+           description => "Privilege options for user-settable tags",
+           format => $user_tag_privs_format,
+       },
+       'registered-tags' => {
+           optional => 1,
+           type => 'string',
+           description => "A list of tags that require a `Sys.Modify` on '/' to set and delete. "
+               ."Tags set here that are also in 'user-tag-access' also require `Sys.Modify`.",
+           pattern => "(?:${PVE::JSONSchema::PVE_TAG_RE};)*${PVE::JSONSchema::PVE_TAG_RE}",
+           typetext => "<tag>[;<tag>...]",
+       },
     },
 };
 
@@ -274,6 +406,10 @@ sub parse_datacenter_config {
 
     $res->{description} = $comment;
 
+    if (my $crs = $res->{crs}) {
+       $res->{crs} = parse_property_string($crs_format, $crs);
+    }
+
     if (my $migration = $res->{migration}) {
        $res->{migration} = parse_property_string($migration_format, $migration);
     }
@@ -285,6 +421,9 @@ sub parse_datacenter_config {
     if (my $ha = $res->{ha}) {
        $res->{ha} = parse_property_string($ha_format, $ha);
     }
+    if (my $notify = $res->{notify}) {
+       $res->{notify} = parse_property_string($notification_format, $notify);
+    }
 
     if (my $u2f = $res->{u2f}) {
        $res->{u2f} = parse_property_string($u2f_format, $u2f);
@@ -294,6 +433,23 @@ sub parse_datacenter_config {
        $res->{webauthn} = parse_property_string($webauthn_format, $webauthn);
     }
 
+    if (my $tag_style = $res->{'tag-style'}) {
+       $res->{'tag-style'} = parse_property_string($tag_style_format, $tag_style);
+    }
+
+    if (my $user_tag_privs = $res->{'user-tag-access'}) {
+       $res->{'user-tag-access'} =
+           parse_property_string($user_tag_privs_format, $user_tag_privs);
+
+       if (my $user_tags = $res->{'user-tag-access'}->{'user-allow-list'}) {
+           $res->{'user-tag-access'}->{'user-allow-list'} = [split(';', $user_tags)];
+       }
+    }
+
+    if (my $admin_tags = $res->{'registered-tags'}) {
+       $res->{'registered-tags'} = [split(';', $admin_tags)];
+    }
+
     # for backwards compatibility only, new migration property has precedence
     if (defined($res->{migration_unsecure})) {
        if (defined($res->{migration}->{type})) {
@@ -326,6 +482,10 @@ sub write_datacenter_config {
        $cfg->{console} = 'html5';
     }
 
+    if (ref(my $crs = $cfg->{crs})) {
+       $cfg->{crs} = PVE::JSONSchema::print_property_string($crs, $crs_format);
+    }
+
     if (ref(my $migration = $cfg->{migration})) {
        $cfg->{migration} = PVE::JSONSchema::print_property_string($migration, $migration_format);
     }
@@ -336,7 +496,7 @@ sub write_datacenter_config {
        my $lower = int($next_id->{lower} // $next_id_format->{lower}->{default});
        my $upper = int($next_id->{upper} // $next_id_format->{upper}->{default});
 
-       die "lower ($lower) <= upper ($upper) boundary rule broken" if $lower > $upper;
+       die "lower ($lower) <= upper ($upper) boundary rule broken\n" if $lower > $upper;
 
        $cfg->{'next-id'} = PVE::JSONSchema::print_property_string($next_id, $next_id_format);
     }
@@ -344,6 +504,9 @@ sub write_datacenter_config {
     if (ref(my $ha = $cfg->{ha})) {
        $cfg->{ha} = PVE::JSONSchema::print_property_string($ha, $ha_format);
     }
+    if (ref(my $notify = $cfg->{notify})) {
+       $cfg->{notify} = PVE::JSONSchema::print_property_string($notify, $notification_format);
+    }
 
     if (ref(my $u2f = $cfg->{u2f})) {
        $cfg->{u2f} = PVE::JSONSchema::print_property_string($u2f, $u2f_format);
@@ -353,6 +516,22 @@ sub write_datacenter_config {
        $cfg->{webauthn} = PVE::JSONSchema::print_property_string($webauthn, $webauthn_format);
     }
 
+    if (ref(my $tag_style = $cfg->{'tag-style'})) {
+       $cfg->{'tag-style'} = PVE::JSONSchema::print_property_string($tag_style, $tag_style_format);
+    }
+
+    if (ref(my $user_tag_privs = $cfg->{'user-tag-access'})) {
+       if (my $user_tags = $user_tag_privs->{'user-allow-list'}) {
+           $user_tag_privs->{'user-allow-list'} = join(';', sort $user_tags->@*);
+       }
+       $cfg->{'user-tag-access'} =
+           PVE::JSONSchema::print_property_string($user_tag_privs, $user_tag_privs_format);
+    }
+
+    if (ref(my $admin_tags = $cfg->{'registered-tags'})) {
+       $cfg->{'registered-tags'} = join(';', sort $admin_tags->@*);
+    }
+
     my $comment = '';
     # add description as comment to top of file
     my $description = $cfg->{description} || '';