1{ config, lib, pkgs, ... }: 2 3with lib; with import ./common.nix {inherit lib;}; 4 5let 6 cfg = config.virtualisation.openstack.glance; 7 commonConf = '' 8 [database] 9 connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}" 10 notification_driver = noop 11 12 [keystone_authtoken] 13 auth_url = ${cfg.authUrl} 14 auth_plugin = password 15 project_name = service 16 project_domain_id = default 17 user_domain_id = default 18 username = ${cfg.serviceUsername} 19 password = ${cfg.servicePassword.pattern} 20 21 [glance_store] 22 default_store = file 23 filesystem_store_datadir = /var/lib/glance/images/ 24 ''; 25 glanceApiConfTpl = pkgs.writeText "glance-api.conf" '' 26 ${commonConf} 27 28 [paste_deploy] 29 flavor = keystone 30 config_file = ${cfg.package}/etc/glance-api-paste.ini 31 ''; 32 glanceRegistryConfTpl = pkgs.writeText "glance-registry.conf" '' 33 ${commonConf} 34 35 [paste_deploy] 36 config_file = ${cfg.package}/etc/glance-registry-paste.ini 37 ''; 38 glanceApiConf = "/var/lib/glance/glance-api.conf"; 39 glanceRegistryConf = "/var/lib/glance/glance-registry.conf"; 40 41in { 42 options.virtualisation.openstack.glance = { 43 package = mkOption { 44 type = types.package; 45 default = pkgs.glance; 46 defaultText = "pkgs.glance"; 47 description = '' 48 Glance package to use. 49 ''; 50 }; 51 52 enable = mkOption { 53 default = false; 54 type = types.bool; 55 description = '' 56 This option enables Glance as a single-machine 57 installation. That is, all of Glance's components are 58 enabled on this machine. This is useful for evaluating and 59 experimenting with Glance. Note we are currently not 60 providing any configurations for a multi-node setup. 61 ''; 62 }; 63 64 authUrl = mkOption { 65 type = types.str; 66 default = http://localhost:5000; 67 description = '' 68 Complete public Identity (Keystone) API endpoint. Note this is 69 unversionned. 70 ''; 71 }; 72 73 serviceUsername = mkOption { 74 type = types.str; 75 default = "glance"; 76 description = '' 77 The Glance service username. This user is created if bootstrap 78 is enable, otherwise it has to be manually created before 79 starting this service. 80 ''; 81 }; 82 83 servicePassword = mkSecretOption { 84 name = "glanceAdminPassword"; 85 description = '' 86 The Glance service user's password. 87 ''; 88 }; 89 90 database = databaseOption "glance"; 91 92 bootstrap = { 93 enable = mkOption { 94 default = false; 95 type = types.bool; 96 description = '' 97 Bootstrap the Glance service by creating the service tenant, 98 an admin account and a public endpoint. This option provides 99 a ready-to-use glance service. This is only done at the 100 first Glance execution by the systemd post start section. 101 The keystone admin account is used to create required 102 Keystone resource for the Glance service. 103 104 <note><para> This option is a helper for setting up 105 development or testing environments.</para></note> 106 ''; 107 }; 108 109 endpointPublic = mkOption { 110 type = types.str; 111 default = "http://localhost:9292"; 112 description = '' 113 The public image endpoint. The link <link 114 xlink:href="http://docs.openstack.org/liberty/install-guide-rdo/keystone-services.html"> 115 create endpoint</link> provides more informations 116 about that. 117 ''; 118 }; 119 120 keystoneAdminUsername = mkOption { 121 type = types.str; 122 default = "admin"; 123 description = '' 124 The keystone admin user name used to create the Glance account. 125 ''; 126 }; 127 128 keystoneAdminPassword = mkSecretOption { 129 name = "keystoneAdminPassword"; 130 description = '' 131 The keystone admin user's password. 132 ''; 133 }; 134 135 keystoneAdminTenant = mkOption { 136 type = types.str; 137 default = "admin"; 138 description = '' 139 The keystone admin tenant used to create the Glance account. 140 ''; 141 }; 142 keystoneAuthUrl = mkOption { 143 type = types.str; 144 default = "http://localhost:5000/v2.0"; 145 description = '' 146 The keystone auth url used to create the Glance account. 147 ''; 148 }; 149 }; 150 }; 151 152 config = mkIf cfg.enable { 153 users.extraUsers = [{ 154 name = "glance"; 155 group = "glance"; 156 uid = config.ids.gids.glance; 157 158 }]; 159 users.extraGroups = [{ 160 name = "glance"; 161 gid = config.ids.gids.glance; 162 }]; 163 164 systemd.services.glance-registry = { 165 description = "OpenStack Glance Registry Daemon"; 166 after = [ "network.target"]; 167 path = [ pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ]; 168 wantedBy = [ "multi-user.target" ]; 169 preStart = '' 170 mkdir -m 775 -p /var/lib/glance/{images,scrubber,image_cache} 171 chown glance:glance /var/lib/glance/{images,scrubber,image_cache} 172 173 # Secret file managment 174 cp ${glanceRegistryConfTpl} ${glanceRegistryConf}; 175 chown glance:glance ${glanceRegistryConf}; 176 chmod 640 ${glanceRegistryConf} 177 ${replaceSecret cfg.database.password glanceRegistryConf} 178 ${replaceSecret cfg.servicePassword glanceRegistryConf} 179 180 cp ${glanceApiConfTpl} ${glanceApiConf}; 181 chown glance:glance ${glanceApiConf}; 182 chmod 640 ${glanceApiConf} 183 ${replaceSecret cfg.database.password glanceApiConf} 184 ${replaceSecret cfg.servicePassword glanceApiConf} 185 186 # Initialise the database 187 ${cfg.package}/bin/glance-manage --config-file=${glanceApiConf} --config-file=${glanceRegistryConf} db_sync 188 ''; 189 postStart = '' 190 set -eu 191 export OS_AUTH_URL=${cfg.bootstrap.keystoneAuthUrl} 192 export OS_USERNAME=${cfg.bootstrap.keystoneAdminUsername} 193 export OS_PASSWORD=${getSecret cfg.bootstrap.keystoneAdminPassword} 194 export OS_TENANT_NAME=${cfg.bootstrap.keystoneAdminTenant} 195 196 # Wait until the keystone is available for use 197 count=0 198 while ! keystone user-get ${cfg.bootstrap.keystoneAdminUsername} > /dev/null 199 do 200 if [ $count -eq 30 ] 201 then 202 echo "Tried 30 times, giving up..." 203 exit 1 204 fi 205 206 echo "Keystone not yet started. Waiting for 1 second..." 207 count=$((count++)) 208 sleep 1 209 done 210 211 # If the service glance doesn't exist, we consider glance is 212 # not initialized 213 if ! keystone service-get glance 214 then 215 keystone service-create --type image --name glance 216 ID=$(keystone service-get glance | awk '/ id / { print $4 }') 217 keystone endpoint-create --region RegionOne --service $ID --internalurl http://localhost:9292 --adminurl http://localhost:9292 --publicurl ${cfg.bootstrap.endpointPublic} 218 219 keystone user-create --name ${cfg.serviceUsername} --tenant service --pass ${getSecret cfg.servicePassword} 220 keystone user-role-add --tenant service --user ${cfg.serviceUsername} --role admin 221 fi 222 ''; 223 serviceConfig = { 224 PermissionsStartOnly = true; # preStart must be run as root 225 TimeoutStartSec = "600"; # 10min for initial db migrations 226 User = "glance"; 227 Group = "glance"; 228 ExecStart = "${cfg.package}/bin/glance-registry --config-file=${glanceRegistryConf}"; 229 }; 230 }; 231 systemd.services.glance-api = { 232 description = "OpenStack Glance API Daemon"; 233 after = [ "glance-registry.service" "network.target"]; 234 requires = [ "glance-registry.service" "network.target"]; 235 wantedBy = [ "multi-user.target" ]; 236 serviceConfig = { 237 PermissionsStartOnly = true; # preStart must be run as root 238 User = "glance"; 239 Group = "glance"; 240 ExecStart = "${cfg.package}/bin/glance-api --config-file=${glanceApiConf}"; 241 }; 242 }; 243 }; 244 245}