source: trunk/packages/xen-3.1/xen-3.1/tools/examples/vtpm-common.sh @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 10.0 KB
Line 
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
19dir=$(dirname "$0")
20. "$dir/logging.sh"
21. "$dir/locking.sh"
22
23VTPMDB="/etc/xen/vtpm.db"
24
25#In the vtpm-impl file some commands should be defined:
26#      vtpm_create, vtpm_setup, vtpm_start, etc. (see below)
27if [ -r "$dir/vtpm-impl.alt" ]; then
28        . "$dir/vtpm-impl.alt"
29elif [ -r "$dir/vtpm-impl" ]; then
30        . "$dir/vtpm-impl"
31else
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        }
59fi
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'
68function 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.
92function 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
120function 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
151function 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
170function 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
205function 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'
229function 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.
243function vtpm_create_instance () {
244        local res instance domname reason
245        domname=$(xenstore_read "$XENBUS_PATH"/domain)
246        reason=$(vtpm_get_create_reason)
247
248        claim_lock vtpmdb
249        instance=$(vtpmdb_find_instance $domname)
250
251        if [ "$instance" == "0" -a "$reason" != "create" ]; then
252                release_lock vtpmdb
253                return
254        fi
255
256        if [ "$instance" == "0" ]; then
257                #Try to give the preferred instance to the domain
258                instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
259                if [ "$instance" != "" ]; then
260                        res=$(vtpmdb_is_free_instancenum $instance)
261                        if [ $res -eq 0 ]; then
262                                instance=$(vtpmdb_get_free_instancenum)
263                        fi
264                else
265                        instance=$(vtpmdb_get_free_instancenum)
266                fi
267
268                vtpm_create $instance
269
270                if [ $vtpm_fatal_error -eq 0 ]; then
271                        vtpmdb_add_instance $domname $instance
272                fi
273        else
274                if [ "$reason" == "resume" ]; then
275                        vtpm_resume $instance
276                else
277                        vtpm_start $instance
278                fi
279        fi
280
281        release_lock vtpmdb
282
283        xenstore_write $XENBUS_PATH/instance $instance
284}
285
286
287#Remove an instance when a VM is terminating or suspending.
288#Since it is assumed that the VM will appear again, the
289#entry is kept in the VTPMDB file.
290function vtpm_remove_instance () {
291        local instance reason domname
292        #Stop script execution quietly if path does not exist (anymore)
293        xenstore-exists "$XENBUS_PATH"/domain
294        domname=$(xenstore_read "$XENBUS_PATH"/domain)
295
296        if [ "$domname" != "" ]; then
297                claim_lock vtpmdb
298
299                instance=$(vtpmdb_find_instance $domname)
300
301                if [ "$instance" != "0" ]; then
302                        vtpm_suspend $instance
303                fi
304
305                release_lock vtpmdb
306        fi
307}
308
309
310#Remove an entry in the VTPMDB file given the domain's name
311#1st parameter: The name of the domain
312function vtpm_delete_instance () {
313        local instance
314
315        claim_lock vtpmdb
316
317        instance=$(vtpmdb_find_instance $1)
318        if [ "$instance" != "0" ]; then
319                vtpmdb_remove_entry $1 $instance
320        fi
321
322        release_lock vtpmdb
323}
324
325# Determine whether the given address is local to this machine
326# Return values:
327#  "-1" : the given machine name is invalid
328#  "0"  : this is not an address of this machine
329#  "1"  : this is an address local to this machine
330function vtpm_isLocalAddress() {
331        local addr res
332        addr=$(ping $1 -c 1 |  \
333               gawk '{ print substr($3,2,length($3)-2); exit }')
334        if [ "$addr" == "" ]; then
335                echo "-1"
336                return
337        fi
338        res=$(ifconfig | grep "inet addr" |  \
339             gawk -vaddr=$addr               \
340             '{                              \
341                if ( addr == substr($2, 6)) {\
342                  print "1";                 \
343                }                            \
344             }'                              \
345            )
346        if [ "$res" == "" ]; then
347                echo "0"
348                return
349        fi
350        echo "1"
351}
352
353# Perform a migration step. This function differentiates between migration
354# to the local host or to a remote machine.
355# Parameters:
356# 1st: destination host to migrate to
357# 2nd: name of the domain to migrate
358# 3rd: the migration step to perform
359function vtpm_migration_step() {
360        local res=$(vtpm_isLocalAddress $1)
361        if [ "$res" == "0" ]; then
362                vtpm_migrate $1 $2 $3
363        else
364                vtpm_migrate_local
365        fi
366}
367
368# Recover from migration due to an error. This function differentiates
369# between migration to the local host or to a remote machine.
370# Parameters:
371# 1st: destination host the migration was going to
372# 2nd: name of the domain that was to be migrated
373# 3rd: the last successful migration step that was done
374function vtpm_recover() {
375        local res
376        res=$(vtpm_isLocalAddress $1)
377        if [ "$res" == "0" ]; then
378                vtpm_migrate_recover $1 $2 $3
379        fi
380}
381
382
383#Determine the domain id given a domain's name.
384#1st parameter: name of the domain
385#return value: domain id  or -1 if domain id could not be determined
386function vtpm_domid_from_name () {
387        local id name ids
388        ids=$(xenstore-list /local/domain)
389        for id in $ids; do
390                name=$(xenstore_read /local/domain/$id/name)
391                if [ "$name" == "$1" ]; then
392                        echo "$id"
393                        return
394                fi
395        done
396        echo "-1"
397}
398
399
400#Add a virtual TPM instance number and its associated domain name
401#to the VTPMDB file and activate usage of this virtual TPM instance
402#by writing the instance number into the xenstore
403#1st parm: name of virtual machine
404#2nd parm: instance of assoicate virtual TPM
405function vtpm_add_and_activate() {
406        local domid=$(vtpm_domid_from_name $1)
407        if [ "$domid" != "-1" ]; then
408                vtpmdb_add_instance $1 $2
409                xenstore-write backend/vtpm/$domid/0/instance $2
410        fi
411}
Note: See TracBrowser for help on using the repository browser.