diff --git a/lower-constraints.txt b/lower-constraints.txt
index 2046b34..e608508 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -84,7 +84,7 @@ python-neutronclient==6.7.0
python-novaclient==10.1.0
python-openstackclient==3.14.0
python-swiftclient==3.5.0
-python-zunclient==1.3.0
+python-zunclient==1.4.0
pytz==2018.3
PyYAML==3.12
rcssmin==1.0.6
diff --git a/requirements.txt b/requirements.txt
index 06b66c1..ca79d11 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,6 +8,6 @@
#
# PBR should always appear first
pbr!=2.1.0,>=2.0.0 # Apache-2.0
-python-zunclient>=1.3.0 # Apache-2.0
+python-zunclient>=1.4.0 # Apache-2.0
horizon>=14.0.0.0b1 # Apache-2.0
diff --git a/zun_ui/api/client.py b/zun_ui/api/client.py
index 538aa9f..3f7aa01 100644
--- a/zun_ui/api/client.py
+++ b/zun_ui/api/client.py
@@ -104,11 +104,11 @@ def _cleanup_params(attrs, check, **params):
run = value
elif key == "cpu":
args[key] = float(value)
- elif key == "memory":
+ elif key == "memory" or key == "disk":
args[key] = int(value)
elif key == "interactive" or key == "mounts" or key == "nets" \
or key == "security_groups" or key == "hints"\
- or key == "auto_remove":
+ or key == "auto_remove" or key == "auto_heal":
args[key] = value
elif key == "restart_policy":
args[key] = utils.check_restart_policy(value)
@@ -267,6 +267,11 @@ def port_update_security_groups(request):
return {"port": port, "security_group": security_groups}
+def availability_zone_list(request):
+ list = zunclient(request).availability_zones.list()
+ return list
+
+
def image_list(request, limit=None, marker=None, sort_key=None,
sort_dir=None, detail=True):
return zunclient(request).images.list(limit, marker, sort_key,
diff --git a/zun_ui/api/rest_api.py b/zun_ui/api/rest_api.py
index 98564f9..1796451 100644
--- a/zun_ui/api/rest_api.py
+++ b/zun_ui/api/rest_api.py
@@ -145,6 +145,22 @@ class Containers(generic.View):
new_container.to_dict())
+@urls.register
+class AvailabilityZones(generic.View):
+ """API for Zun AvailabilityZones"""
+ url_regex = r'zun/availability_zones/$'
+
+ @rest_utils.ajax()
+ def get(self, request):
+ """Get a list of the Zun AvailabilityZones.
+
+ The returned result is an object with property 'items' and each
+ item under this is a Zun AvailabilityZones.
+ """
+ result = client.availability_zone_list(request)
+ return {'items': [i.to_dict() for i in result]}
+
+
@urls.register
class Images(generic.View):
"""API for Zun Images"""
diff --git a/zun_ui/static/dashboard/container/containers/actions/workflow/spec.help.html b/zun_ui/static/dashboard/container/containers/actions/workflow/spec.help.html
index 33c1ace..3c2ef05 100644
--- a/zun_ui/static/dashboard/container/containers/actions/workflow/spec.help.html
+++ b/zun_ui/static/dashboard/container/containers/actions/workflow/spec.help.html
@@ -1,10 +1,16 @@
- - CPU
- - The number of virtual cpus.
- - Memory
- - The container memory size in MiB.
- Runtime
- The runtime to use for this container. Default: "runc"
+ - CPU
+ - The number of virtual CPUs.
+ - Memory
+ - The container memory size in MiB.
+ - Disk
+ - The disk size in GiB for per container.
+ - Availability Zone
+ - The availability zone of the container.
- Exit Policy
- Policy to apply when a container exits.
+ - Auto Heal
+ - The flag of healing non-existent container in docker.
diff --git a/zun_ui/static/dashboard/container/containers/actions/workflow/workflow.service.js b/zun_ui/static/dashboard/container/containers/actions/workflow/workflow.service.js
index 35795df..0c73afa 100644
--- a/zun_ui/static/dashboard/container/containers/actions/workflow/workflow.service.js
+++ b/zun_ui/static/dashboard/container/containers/actions/workflow/workflow.service.js
@@ -59,6 +59,9 @@
{value: "unless-stopped", name: gettext("Restart if stopped")},
{value: "remove", name: gettext("Remove container")}
];
+ var availabilityZones = [
+ {value: "", name: gettext("Select availability zone.")}
+ ];
// schema
schema = {
@@ -108,6 +111,15 @@
type: "number",
minimum: 4
},
+ disk: {
+ title: gettext("Disk"),
+ type: "number",
+ minimum: 0
+ },
+ availability_zone: {
+ title: gettext("Availability Zone"),
+ type: "string"
+ },
exit_policy: {
title: gettext("Exit Policy"),
type: "string"
@@ -117,6 +129,10 @@
type: "number",
minimum: 0
},
+ auto_heal: {
+ title: gettext("Enable auto heal"),
+ type: "boolean"
+ },
// misc
workdir: {
title: gettext("Working Directory"),
@@ -255,6 +271,29 @@
}
]
},
+ {
+ type: "section",
+ htmlClass: "col-xs-6",
+ items: [
+ {
+ key: "disk",
+ step: 1,
+ placeholder: gettext("The disk size in GiB for per container.")
+ }
+ ]
+ },
+ {
+ type: "section",
+ htmlClass: "col-xs-6",
+ items: [
+ {
+ key: "availability_zone",
+ readonly: action === "update",
+ type: "select",
+ titleMap: availabilityZones
+ }
+ ]
+ },
{
type: "section",
htmlClass: "col-xs-6",
@@ -269,7 +308,7 @@
if (notOnFailure) {
model.restart_policy_max_retry = "";
}
- form[0].tabs[1].items[5].items[0].readonly = notOnFailure;
+ form[0].tabs[1].items[7].items[0].readonly = notOnFailure;
// set auto_remove whether exit_policy is "remove".
// if exit_policy is set as "remove", clear restart_policy.
// otherwise, set restart_policy as same value as exit_policy.
@@ -293,6 +332,16 @@
readonly: true
}
]
+ },
+ {
+ type: "section",
+ htmlClass: "col-xs-12",
+ items: [
+ {
+ key: "auto_heal",
+ readonly: action === "update"
+ }
+ ]
}
]
},
@@ -462,10 +511,13 @@
runtime: "",
cpu: "",
memory: "",
+ disks: "",
+ availability_zone: "",
exit_policy: "",
restart_policy: "",
restart_policy_max_retry: "",
auto_remove: false,
+ auto_heal: false,
// mounts
mounts: [],
// networks
@@ -510,6 +562,7 @@
getVolumes();
getNetworks();
securityGroup.query().then(onGetSecurityGroups);
+ zun.getZunAvailabilityZones().then(onGetZunServices);
});
// get container when action equals "update"
@@ -681,6 +734,15 @@
return response;
}
+ // get availability zones from zun services
+ function onGetZunServices(response) {
+ var azs = [];
+ response.data.items.forEach(function (service) {
+ azs.push({value: service.availability_zone, name: service.availability_zone});
+ });
+ push.apply(availabilityZones, azs);
+ }
+
var config = {
title: title,
submitText: submitText,
diff --git a/zun_ui/static/dashboard/container/containers/containers.module.js b/zun_ui/static/dashboard/container/containers/containers.module.js
index e49c8ee..81792ac 100644
--- a/zun_ui/static/dashboard/container/containers/containers.module.js
+++ b/zun_ui/static/dashboard/container/containers/containers.module.js
@@ -144,9 +144,11 @@
function containerProperties() {
return {
'addresses': { label: gettext('Addresses'), filters: ['noValue', 'json'] },
+ 'auto_heal': { label: gettext('Auto Heal'), filters: ['yesno'] },
'auto_remove': { label: gettext('Auto Remove'), filters: ['yesno'] },
'command': { label: gettext('Command'), filters: ['noValue'] },
'cpu': { label: gettext('CPU'), filters: ['noValue'] },
+ 'disk': { label: gettext('Disk'), filters: ['gb', 'noValue'] },
'environment': { label: gettext('Environment'), filters: ['noValue', 'json'] },
'host': { label: gettext('Host'), filters: ['noValue'] },
'hostname': { label: gettext('Hostname'), filters: ['noValue'] },
diff --git a/zun_ui/static/dashboard/container/containers/details/overview.html b/zun_ui/static/dashboard/container/containers/details/overview.html
index 38753de..1cff23a 100644
--- a/zun_ui/static/dashboard/container/containers/details/overview.html
+++ b/zun_ui/static/dashboard/container/containers/details/overview.html
@@ -19,7 +19,7 @@
cls="dl-horizontal"
item="ctrl.container"
property-groups="[['image', 'image_driver', 'image_pull_policy', 'hostname', 'runtime',
- 'cpu', 'memory', 'restart_policy', 'auto_remove',
+ 'cpu', 'memory', 'disk', 'restart_policy', 'auto_remove', 'auto_heal',
'addresses', 'ports', 'security_groups']]">
diff --git a/zun_ui/static/dashboard/container/zun.service.js b/zun_ui/static/dashboard/container/zun.service.js
index 51e5647..fe01f7a 100644
--- a/zun_ui/static/dashboard/container/zun.service.js
+++ b/zun_ui/static/dashboard/container/zun.service.js
@@ -26,6 +26,7 @@
function ZunAPI(apiService, toastService, gettext) {
var containersPath = '/api/zun/containers/';
+ var zunAvailabilityZonesPath = '/api/zun/availability_zones/';
var imagesPath = '/api/zun/images/';
var service = {
createContainer: createContainer,
@@ -48,6 +49,7 @@
attachNetwork: attachNetwork,
detachNetwork: detachNetwork,
updatePortSecurityGroup: updatePortSecurityGroup,
+ getZunAvailabilityZones: getZunAvailabilityZones,
pullImage: pullImage,
getImages: getImages
};
@@ -177,6 +179,15 @@
.error(error(msg));
}
+ //////////////////////////////
+ // Zun AvailabilityZones //
+ //////////////////////////////
+
+ function getZunAvailabilityZones() {
+ var msg = gettext('Unable to retrieve the Zun Availability Zones.');
+ return apiService.get(zunAvailabilityZonesPath).error(error(msg));
+ }
+
////////////
// Images //
////////////