~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/hotplug/Linux/vtpm-common.sh

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright (c) 2005 IBM Corporation
 
3
# Copyright (c) 2005 XenSource Ltd.
 
4
#
 
5
# This library is free software; you can redistribute it and/or
 
6
# modify it under the terms of version 2.1 of the GNU Lesser General Public
 
7
# License as published by the Free Software Foundation.
 
8
#
 
9
# This library is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
# Lesser General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU Lesser General Public
 
15
# License along with this library; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
#
 
18
 
 
19
dir=$(dirname "$0")
 
20
. "$dir/logging.sh"
 
21
. "$dir/locking.sh"
 
22
 
 
23
VTPMDB="/var/vtpm/vtpm.db"
 
24
 
 
25
#In the vtpm-impl file some commands should be defined:
 
26
#      vtpm_create, vtpm_setup, vtpm_start, etc. (see below)
 
27
if [ -r "$dir/vtpm-impl.alt" ]; then
 
28
        . "$dir/vtpm-impl.alt"
 
29
elif [ -r "$dir/vtpm-impl" ]; then
 
30
        . "$dir/vtpm-impl"
 
31
else
 
32
        function vtpm_create () {
 
33
                true
 
34
        }
 
35
        function vtpm_setup() {
 
36
                true
 
37
        }
 
38
        function vtpm_start() {
 
39
                true
 
40
        }
 
41
        function vtpm_suspend() {
 
42
                true
 
43
        }
 
44
        function vtpm_resume() {
 
45
                true
 
46
        }
 
47
        function vtpm_delete() {
 
48
                true
 
49
        }
 
50
        function vtpm_migrate() {
 
51
                echo "Error: vTPM migration accross machines not implemented."
 
52
        }
 
53
        function vtpm_migrate_local() {
 
54
                echo "Error: local vTPM migration not supported"
 
55
        }
 
56
        function vtpm_migrate_recover() {
 
57
                true
 
58
        }
 
59
fi
 
60
 
 
61
 
 
62
#Find the instance number for the vtpm given the name of the domain
 
63
# Parameters
 
64
# - vmname : the name of the vm
 
65
# Return value
 
66
#  Returns '0' if instance number could not be found, otherwise
 
67
#  it returns the instance number in the variable 'instance'
 
68
function vtpmdb_find_instance () {
 
69
        local vmname ret instance
 
70
        vmname=$1
 
71
        ret=0
 
72
 
 
73
        instance=$(cat $VTPMDB |                   \
 
74
                  awk -vvmname=$vmname             \
 
75
                  '{                               \
 
76
                     if ( 1 != index($1,"#")) {    \
 
77
                       if ( $1 == vmname ) {       \
 
78
                         print $2;                 \
 
79
                         exit;                     \
 
80
                       }                           \
 
81
                     }                             \
 
82
                   }')
 
83
        if [ "$instance" != "" ]; then
 
84
                ret=$instance
 
85
        fi
 
86
        echo "$ret"
 
87
}
 
88
 
 
89
 
 
90
# Check whether a particular instance number is still available
 
91
# returns "0" if it is not available, "1" otherwise.
 
92
function vtpmdb_is_free_instancenum () {
 
93
        local instance instances avail i
 
94
        instance=$1
 
95
        avail=1
 
96
        #Allowed instance number range: 1-255
 
97
        if [ $instance -eq 0 -o $instance -gt 255 ]; then
 
98
                avail=0
 
99
        else
 
100
                instances=$(cat $VTPMDB |                \
 
101
                           gawk                          \
 
102
                           '{                            \
 
103
                               if (1 != index($1,"#")) { \
 
104
                                 printf("%s ",$2);       \
 
105
                               }                         \
 
106
                            }')
 
107
                for i in $instances; do
 
108
                        if [ $i -eq $instance ]; then
 
109
                                avail=0
 
110
                                break
 
111
                        fi
 
112
                done
 
113
        fi
 
114
        echo "$avail"
 
115
}
 
116
 
 
117
 
 
118
# Get an available instance number given the database
 
119
# Returns an unused instance number
 
120
function vtpmdb_get_free_instancenum () {
 
121
        local ctr instances don found
 
122
        instances=$(cat $VTPMDB |                \
 
123
                   gawk                          \
 
124
                   '{                            \
 
125
                       if (1 != index($1,"#")) { \
 
126
                         printf("%s ",$2);       \
 
127
                       }                         \
 
128
                    }')
 
129
        ctr=1
 
130
        don=0
 
131
        while [ $don -eq 0 ]; do
 
132
                found=0
 
133
                for i in $instances; do
 
134
                        if [ $i -eq $ctr ]; then
 
135
                                found=1;
 
136
                                break;
 
137
                        fi
 
138
                done
 
139
 
 
140
                if [ $found -eq 0 ]; then
 
141
                        don=1
 
142
                        break
 
143
                fi
 
144
                let ctr=ctr+1
 
145
        done
 
146
        echo "$ctr"
 
147
}
 
148
 
 
149
 
 
150
# Add a domain name and instance number to the DB file
 
151
function vtpmdb_add_instance () {
 
152
        local res vmname inst
 
153
        vmname=$1
 
154
        inst=$2
 
155
 
 
156
        if [ ! -f $VTPMDB ]; then
 
157
                echo "#Database for VM to vTPM association" > $VTPMDB
 
158
                echo "#1st column: domain name" >> $VTPMDB
 
159
                echo "#2nd column: TPM instance number" >> $VTPMDB
 
160
        fi
 
161
        res=$(vtpmdb_validate_entry $vmname $inst)
 
162
        if [ $res -eq 0 ]; then
 
163
                echo "$vmname $inst" >> $VTPMDB
 
164
        fi
 
165
}
 
166
 
 
167
 
 
168
#Validate whether an entry is the same as passed to this
 
169
#function
 
170
function vtpmdb_validate_entry () {
 
171
        local res rc vmname inst
 
172
        rc=0
 
173
        vmname=$1
 
174
        inst=$2
 
175
 
 
176
        res=$(cat $VTPMDB |            \
 
177
             gawk -vvmname=$vmname     \
 
178
                  -vinst=$inst         \
 
179
             '{                        \
 
180
                 if ( 1 == index($1,"#")) {\
 
181
                 } else                \
 
182
                 if ( $1 == vmname &&  \
 
183
                      $2 == inst) {    \
 
184
                    printf("1");       \
 
185
                    exit;              \
 
186
                 } else                \
 
187
                 if ( $1 == vmname ||  \
 
188
                      $2 == inst) {    \
 
189
                    printf("2");       \
 
190
                    exit;              \
 
191
                 }                     \
 
192
             }')
 
193
 
 
194
        if [ "$res" == "1" ]; then
 
195
                rc=1
 
196
        elif [ "$res" == "2" ]; then
 
197
                rc=2
 
198
        fi
 
199
        echo "$rc"
 
200
}
 
201
 
 
202
 
 
203
#Remove an entry from the vTPM database given its domain name
 
204
#and instance number
 
205
function vtpmdb_remove_entry () {
 
206
        local vmname instance VTPMDB_TMP
 
207
        vmname=$1
 
208
        instance=$2
 
209
        VTPMDB_TMP="$VTPMDB".tmp
 
210
 
 
211
        $(cat $VTPMDB |            \
 
212
         gawk -vvmname=$vmname     \
 
213
         '{                        \
 
214
            if ( $1 != vmname ) {  \
 
215
              print $0;            \
 
216
            }                      \
 
217
         '} > $VTPMDB_TMP)
 
218
        if [ -e $VTPMDB_TMP ]; then
 
219
                mv -f $VTPMDB_TMP $VTPMDB
 
220
                vtpm_delete $instance
 
221
        else
 
222
                log err "Error creating temporary file '$VTPMDB_TMP'."
 
223
        fi
 
224
}
 
225
 
 
226
 
 
227
# Find the reason for the creation of this device:
 
228
# Returns 'resume' or 'create'
 
229
function vtpm_get_create_reason () {
 
230
        local resume
 
231
        resume=$(xenstore_read $XENBUS_PATH/resume)
 
232
        if [ "$resume" == "True" ]; then
 
233
                echo "resume"
 
234
        else
 
235
                echo "create"
 
236
        fi
 
237
}
 
238
 
 
239
 
 
240
#Create a vTPM instance
 
241
# If no entry in the TPM database is found, the instance is
 
242
# created and an entry added to the database.
 
243
function vtpm_create_instance () {
 
244
        local res instance domname reason uuid
 
245
        uuid=$(xenstore_read "$XENBUS_PATH"/uuid)
 
246
        reason=$(vtpm_get_create_reason)
 
247
 
 
248
        claim_lock vtpmdb
 
249
 
 
250
        instance="0"
 
251
 
 
252
        if [ "$uuid" != "" ]; then
 
253
                instance=$(vtpmdb_find_instance $uuid)
 
254
        fi
 
255
        if [ "$instance" == "0" ]; then
 
256
                domname=$(xenstore_read "$XENBUS_PATH"/domain)
 
257
                instance=$(vtpmdb_find_instance $domname)
 
258
        fi
 
259
 
 
260
        if [ "$instance" == "0" -a "$reason" != "create" ]; then
 
261
                release_lock vtpmdb
 
262
                return
 
263
        fi
 
264
 
 
265
        if [ "$instance" == "0" ]; then
 
266
                #Try to give the preferred instance to the domain
 
267
                instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
 
268
                if [ "$instance" != "" ]; then
 
269
                        res=$(vtpmdb_is_free_instancenum $instance)
 
270
                        if [ $res -eq 0 ]; then
 
271
                                instance=$(vtpmdb_get_free_instancenum)
 
272
                        fi
 
273
                else
 
274
                        instance=$(vtpmdb_get_free_instancenum)
 
275
                fi
 
276
 
 
277
                vtpm_create $instance
 
278
 
 
279
                if [ $vtpm_fatal_error -eq 0 ]; then
 
280
                        if [ "$uuid" != "" ]; then
 
281
                                vtpmdb_add_instance $uuid $instance
 
282
                        else
 
283
                                vtpmdb_add_instance $domname $instance
 
284
                        fi
 
285
                fi
 
286
        else
 
287
                if [ "$reason" == "resume" ]; then
 
288
                        vtpm_resume $instance
 
289
                else
 
290
                        vtpm_start $instance
 
291
                fi
 
292
        fi
 
293
 
 
294
        release_lock vtpmdb
 
295
 
 
296
        xenstore_write $XENBUS_PATH/instance $instance
 
297
}
 
298
 
 
299
 
 
300
#Remove an instance when a VM is terminating or suspending.
 
301
#Since it is assumed that the VM will appear again, the
 
302
#entry is kept in the VTPMDB file.
 
303
function vtpm_remove_instance () {
 
304
        local instance reason domname uuid
 
305
        #Stop script execution quietly if path does not exist (anymore)
 
306
        xenstore-exists "$XENBUS_PATH"/domain
 
307
        uuid=$(xenstore_read "$XENBUS_PATH"/uuid)
 
308
 
 
309
        claim_lock vtpmdb
 
310
 
 
311
        instance="0"
 
312
 
 
313
        if [ "$uuid" != "" ]; then
 
314
                instance=$(vtpmdb_find_instance $uuid)
 
315
        fi
 
316
 
 
317
        if [ "$instance" == "0" ]; then
 
318
                domname=$(xenstore_read "$XENBUS_PATH"/domain)
 
319
                instance=$(vtpmdb_find_instance $domname)
 
320
        fi
 
321
 
 
322
        if [ "$instance" != "0" ]; then
 
323
                vtpm_suspend $instance
 
324
        fi
 
325
 
 
326
        release_lock vtpmdb
 
327
}
 
328
 
 
329
 
 
330
#Remove an entry in the VTPMDB file given the domain's name
 
331
#1st parameter: The name of the domain
 
332
function vtpm_delete_instance () {
 
333
        local instance
 
334
 
 
335
        claim_lock vtpmdb
 
336
 
 
337
        instance=$(vtpmdb_find_instance $1)
 
338
        if [ "$instance" != "0" ]; then
 
339
                vtpmdb_remove_entry $1 $instance
 
340
        fi
 
341
 
 
342
        release_lock vtpmdb
 
343
}
 
344
 
 
345
# Determine whether the given address is local to this machine
 
346
# Return values:
 
347
#  "-1" : the given machine name is invalid
 
348
#  "0"  : this is not an address of this machine
 
349
#  "1"  : this is an address local to this machine
 
350
function vtpm_isLocalAddress() {
 
351
        local addr res
 
352
        addr=$(ping $1 -c 1 |  \
 
353
               gawk '{ print substr($3,2,length($3)-2); exit }')
 
354
        if [ "$addr" == "" ]; then
 
355
                echo "-1"
 
356
                return
 
357
        fi
 
358
        res=$(ifconfig | grep "inet addr" |  \
 
359
             gawk -vaddr=$addr               \
 
360
             '{                              \
 
361
                if ( addr == substr($2, 6)) {\
 
362
                  print "1";                 \
 
363
                }                            \
 
364
             }'                              \
 
365
            )
 
366
        if [ "$res" == "" ]; then
 
367
                echo "0"
 
368
                return
 
369
        fi
 
370
        echo "1"
 
371
}
 
372
 
 
373
# Perform a migration step. This function differentiates between migration
 
374
# to the local host or to a remote machine.
 
375
# Parameters:
 
376
# 1st: destination host to migrate to
 
377
# 2nd: name of the domain to migrate
 
378
# 3rd: the migration step to perform
 
379
function vtpm_migration_step() {
 
380
        local res=$(vtpm_isLocalAddress $1)
 
381
        if [ "$res" == "0" ]; then
 
382
                vtpm_migrate $1 $2 $3
 
383
        else
 
384
                vtpm_migrate_local
 
385
        fi
 
386
}
 
387
 
 
388
# Recover from migration due to an error. This function differentiates
 
389
# between migration to the local host or to a remote machine.
 
390
# Parameters:
 
391
# 1st: destination host the migration was going to
 
392
# 2nd: name of the domain that was to be migrated
 
393
# 3rd: the last successful migration step that was done
 
394
function vtpm_recover() {
 
395
        local res
 
396
        res=$(vtpm_isLocalAddress $1)
 
397
        if [ "$res" == "0" ]; then
 
398
                vtpm_migrate_recover $1 $2 $3
 
399
        fi
 
400
}
 
401
 
 
402
 
 
403
#Determine the domain id given a domain's name.
 
404
#1st parameter: name of the domain
 
405
#return value: domain id  or -1 if domain id could not be determined
 
406
function vtpm_domid_from_name () {
 
407
        local id name ids
 
408
        ids=$(xenstore-list /local/domain)
 
409
        for id in $ids; do
 
410
                name=$(xenstore-read /local/domain/$id/name)
 
411
                if [ "$name" == "$1" ]; then
 
412
                        echo "$id"
 
413
                        return
 
414
                fi
 
415
        done
 
416
        echo "-1"
 
417
}
 
418
 
 
419
#Determine the virtual TPM's instance number using the domain ID.
 
420
#1st parm: domain ID
 
421
function vtpm_uuid_by_domid() {
 
422
        echo $(xenstore-read /local/domain/0/backend/vtpm/$1/0/uuid)
 
423
}
 
424
 
 
425
 
 
426
# Determine the vTPM's UUID by the name of the VM
 
427
function vtpm_uuid_from_vmname() {
 
428
        local domid=$(vtpm_domid_from_name $1)
 
429
        if [ "$domid" != "-1" ]; then
 
430
                echo $(vtpm_uuid_by_domid $domid)
 
431
                return
 
432
        fi
 
433
        echo ""
 
434
}
 
435
 
 
436
#Add a virtual TPM instance number and its associated domain name
 
437
#to the VTPMDB file and activate usage of this virtual TPM instance
 
438
#by writing the instance number into the xenstore
 
439
#1st parm: name of virtual machine
 
440
#2nd parm: instance of associated virtual TPM
 
441
function vtpm_add_and_activate() {
 
442
        local domid=$(vtpm_domid_from_name $1)
 
443
        local vtpm_uuid=$(vtpm_uuid_from_vmname $1)
 
444
        if [ "$vtpm_uuid" != "" -a "$domid" != "-1" ]; then
 
445
                vtpmdb_add_instance $vtpm_uuid $2
 
446
                xenstore-write backend/vtpm/$domid/0/instance $2
 
447
        fi
 
448
}