Skip to content

Commit 4d3ad75

Browse files
authored
Merge pull request #767 from Mirantis/ivan4th/persistent-rootfs
Add persistent root filesystem
2 parents 8638a35 + 37e2ee7 commit 4d3ad75

File tree

44 files changed

+1270
-92
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1270
-92
lines changed
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
kind: PersistentVolumeClaim
3+
apiVersion: v1
4+
metadata:
5+
name: local-block-pvc
6+
spec:
7+
accessModes:
8+
- ReadWriteOnce
9+
volumeMode: Block
10+
storageClassName: local-storage
11+
resources:
12+
requests:
13+
storage: 100Mi
14+
---
15+
apiVersion: v1
16+
kind: PersistentVolume
17+
metadata:
18+
name: local-block-pv
19+
spec:
20+
capacity:
21+
storage: 100Mi
22+
accessModes:
23+
- ReadWriteOnce
24+
persistentVolumeReclaimPolicy: Retain
25+
storageClassName: local-storage
26+
volumeMode: Block
27+
local:
28+
# set up with:
29+
# docker exec kube-node-1 /bin/bash -c 'dd if=/dev/zero of=/rawtest bs=1M count=1000 && losetup -f /rawtest --show'
30+
path: /dev/loop0
31+
claimRef:
32+
name: local-block-pvc
33+
namespace: default
34+
nodeAffinity:
35+
required:
36+
nodeSelectorTerms:
37+
- matchExpressions:
38+
- key: kubernetes.io/hostname
39+
operator: In
40+
values:
41+
- kube-node-1
42+
---
43+
apiVersion: v1
44+
kind: Pod
45+
metadata:
46+
name: cirros-vm-p
47+
annotations:
48+
kubernetes.io/target-runtime: virtlet.cloud
49+
# CirrOS doesn't load nocloud data from SCSI CD-ROM for some reason
50+
VirtletDiskDriver: virtio
51+
VirtletSSHKeys: |
52+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaJEcFDXEK2ZbX0ZLS1EIYFZRbDAcRfuVjpstSc0De8+sV1aiu+dePxdkuDRwqFtCyk6dEZkssjOkBXtri00MECLkir6FcH3kKOJtbJ6vy3uaJc9w1ERo+wyl6SkAh/+JTJkp7QRXj8oylW5E20LsbnA/dIwWzAF51PPwF7A7FtNg9DnwPqMkxFo1Th/buOMKbP5ZA1mmNNtmzbMpMfJATvVyiv3ccsSJKOiyQr6UG+j7sc/7jMVz5Xk34Vd0l8GwcB0334MchHckmqDB142h/NCWTr8oLakDNvkfC1YneAfAO41hDkUbxPtVBG5M/o7P4fxoqiHEX+ZLfRxDtHB53 me@localhost
53+
spec:
54+
affinity:
55+
nodeAffinity:
56+
requiredDuringSchedulingIgnoredDuringExecution:
57+
nodeSelectorTerms:
58+
- matchExpressions:
59+
- key: extraRuntime
60+
operator: In
61+
values:
62+
- virtlet
63+
# This is the number of seconds Virtlet gives the VM to shut down cleanly.
64+
# The default value of 30 seconds is ok for containers but probably too
65+
# low for VM, so overriding it here is strongly advised.
66+
terminationGracePeriodSeconds: 120
67+
containers:
68+
- name: cirros-vm
69+
image: virtlet.cloud/cirros
70+
imagePullPolicy: IfNotPresent
71+
# tty and stdin required for `kubectl attach -t` to work
72+
tty: true
73+
stdin: true
74+
volumeDevices:
75+
- devicePath: /
76+
name: testpvc
77+
volumes:
78+
- name: testpvc
79+
persistentVolumeClaim:
80+
claimName: local-block-pvc

pkg/image/fake/store.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,13 @@ func (s *FakeStore) GC() error {
119119
return nil
120120
}
121121

122-
// GetImagePathAndVirtualSize implements GC method of Store interface.
123-
func (s *FakeStore) GetImagePathAndVirtualSize(imageName string) (string, uint64, error) {
122+
// GetImagePathDigestAndVirtualSize implements GetImagePathDigestAndVirtualSize method of Store interface.
123+
func (s *FakeStore) GetImagePathDigestAndVirtualSize(imageName string) (string, digest.Digest, uint64, error) {
124124
img, found := s.images[imageName]
125125
if !found {
126-
return "", 0, fmt.Errorf("image not found: %q", imageName)
126+
return "", "", 0, fmt.Errorf("image not found: %q", imageName)
127127
}
128-
return img.Path, img.Size, nil
128+
return img.Path, digest.Digest(img.Digest), img.Size, nil
129129
}
130130

131131
// SetRefGetter implements SetRefGetter method of Store interface.

pkg/image/image.go

+22-18
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ type Store interface {
8181
// GC removes all unused or partially downloaded images.
8282
GC() error
8383

84-
// GetImagePathAndVirtualSize returns the path to image data
85-
// and virtual size for the specified image. It accepts
86-
// an image reference or a digest.
87-
GetImagePathAndVirtualSize(ref string) (string, uint64, error)
84+
// GetImagePathDigestAndVirtualSize returns the path to image
85+
// data, the digest and the virtual size for the specified
86+
// image. It accepts an image reference or a digest.
87+
GetImagePathDigestAndVirtualSize(ref string) (string, digest.Digest, uint64, error)
8888

8989
// SetRefGetter sets a function that will be used to determine
9090
// the set of images that are currently in use.
@@ -472,30 +472,33 @@ func (s *FileStore) GC() error {
472472
return nil
473473
}
474474

475-
// GetImagePathAndVirtualSize implements GC method of Store interface.
476-
func (s *FileStore) GetImagePathAndVirtualSize(ref string) (string, uint64, error) {
475+
// GetImagePathDigestAndVirtualSize implements GetImagePathDigestAndVirtualSize method of Store interface.
476+
func (s *FileStore) GetImagePathDigestAndVirtualSize(ref string) (string, digest.Digest, uint64, error) {
477477
s.Lock()
478478
defer s.Unlock()
479-
glog.V(3).Infof("GetImagePathAndVirtualSize(): %q", ref)
479+
glog.V(3).Infof("GetImagePathDigestAndVirtualSize(): %q", ref)
480480

481481
var pathViaDigest, pathViaName string
482482
// parsing digest as ref gives bad results
483-
if d, err := digest.Parse(ref); err == nil {
483+
d, err := digest.Parse(ref)
484+
if err == nil {
484485
if d.Algorithm() != digest.SHA256 {
485-
return "", 0, fmt.Errorf("bad image digest (need sha256): %q", d)
486+
return "", "", 0, fmt.Errorf("bad image digest (need sha256): %q", d)
486487
}
487488
pathViaDigest = s.dataFileName(d.Hex())
488489
} else {
489490
parsed, err := reference.Parse(ref)
490491
if err != nil {
491-
return "", 0, fmt.Errorf("bad image reference %q: %v", ref, err)
492+
return "", "", 0, fmt.Errorf("bad image reference %q: %v", ref, err)
492493
}
493494

495+
d = ""
494496
if digested, ok := parsed.(reference.Digested); ok {
495497
if digested.Digest().Algorithm() != digest.SHA256 {
496-
return "", 0, fmt.Errorf("bad image digest (need sha256): %q", digested.Digest())
498+
return "", "", 0, fmt.Errorf("bad image digest (need sha256): %q", digested.Digest())
497499
}
498-
pathViaDigest = s.dataFileName(digested.Digest().Hex())
500+
d = digested.Digest()
501+
pathViaDigest = s.dataFileName(d.Hex())
499502
}
500503

501504
if named, ok := parsed.(reference.Named); ok && named.Name() != "" {
@@ -504,35 +507,36 @@ func (s *FileStore) GetImagePathAndVirtualSize(ref string) (string, uint64, erro
504507
glog.Warningf("error reading link %q: %v", pathViaName, err)
505508
} else {
506509
pathViaName = filepath.Join(s.linkDir(), pathViaName)
510+
d = digest.NewDigestFromHex(string(digest.SHA256), filepath.Base(pathViaName))
507511
}
508512
}
509513
}
510514

511515
path := pathViaDigest
512516
switch {
513517
case pathViaDigest == "" && pathViaName == "":
514-
return "", 0, fmt.Errorf("bad image reference %q", ref)
518+
return "", "", 0, fmt.Errorf("bad image reference %q", ref)
515519
case pathViaDigest == "":
516520
path = pathViaName
517521
case pathViaName != "":
518522
fi1, err := os.Stat(pathViaName)
519523
if err != nil {
520-
return "", 0, err
524+
return "", "", 0, err
521525
}
522526
fi2, err := os.Stat(pathViaDigest)
523527
if err != nil {
524-
return "", 0, err
528+
return "", "", 0, err
525529
}
526530
if !os.SameFile(fi1, fi2) {
527-
return "", 0, fmt.Errorf("digest / name path mismatch: %q vs %q", pathViaDigest, pathViaName)
531+
return "", "", 0, fmt.Errorf("digest / name path mismatch: %q vs %q", pathViaDigest, pathViaName)
528532
}
529533
}
530534

531535
vsize, err := s.vsizeFunc(path)
532536
if err != nil {
533-
return "", 0, fmt.Errorf("error getting image size for %q: %v", path, err)
537+
return "", "", 0, fmt.Errorf("error getting image size for %q: %v", path, err)
534538
}
535-
return path, vsize, nil
539+
return path, d, vsize, nil
536540
}
537541

538542
// SetRefGetter implements SetRefGetter method of Store interface.

pkg/image/image_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,13 @@ func (tst *ifsTester) verifyListImages(filter string, expectedImages ...*Image)
187187
}
188188

189189
func (tst *ifsTester) verifyImage(ref string, expectedContents string) {
190-
if path, vsize, err := tst.store.GetImagePathAndVirtualSize(ref); err != nil {
190+
if path, digest, vsize, err := tst.store.GetImagePathDigestAndVirtualSize(ref); err != nil {
191191
tst.t.Errorf("GetImagePathAndVirtualSize(): %v", err)
192192
} else {
193+
expectedDigest := "sha256:" + sha256str(expectedContents)
194+
if string(digest) != expectedDigest {
195+
tst.t.Errorf("bad digest: %s instead of %s", digest, expectedDigest)
196+
}
193197
tst.verifyFileContents(path, expectedContents)
194198
expectedVirtualSize := uint64(len(expectedContents)) + 1000
195199
if vsize != expectedVirtualSize {

pkg/libvirttools/TestContainerLifecycle.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
- name: 'domain conn: ListDomains'
22
value: []
3-
- name: GetImagePathAndVirtualSize
3+
- name: GetImagePathDigestAndVirtualSize
44
value: fake/image1
55
- name: 'storage: CreateStoragePool'
66
value: |-

pkg/libvirttools/TestDomainDefinitions__ceph_flexvolume.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__cloud-init.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__cloud-init_with_user_data.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
- name: GetImagePathDigestAndVirtualSize
2+
value: fake/image1
3+
- name: CMD
4+
value:
5+
cmd: blockdev --getsz /fakedev/69eec606-0493-5825-73a4-c5e0c0236155/volumeDevices/kubernetes.io~local-volume/root
6+
stdout: "1000"
7+
- name: CMD
8+
value:
9+
cmd: dmsetup create virtlet-dm-69eec606-0493-5825-73a4-c5e0c0236155
10+
stdin: |
11+
0 999 linear /fakedev/69eec606-0493-5825-73a4-c5e0c0236155/volumeDevices/kubernetes.io~local-volume/root 1
12+
- name: CMD
13+
value:
14+
cmd: qemu-img convert -O raw /fake/volume/path /dev/mapper/virtlet-dm-69eec606-0493-5825-73a4-c5e0c0236155
15+
- name: 'domain conn: DefineDomain'
16+
value: |-
17+
<domain type="kvm">
18+
<name>virtlet-231700d5-c9a6-container1</name>
19+
<uuid>231700d5-c9a6-5a49-738d-99a954c51550</uuid>
20+
<memory unit="MiB">1024</memory>
21+
<vcpu>1</vcpu>
22+
<cputune>
23+
<shares>0</shares>
24+
<period>0</period>
25+
<quota>0</quota>
26+
</cputune>
27+
<os>
28+
<type>hvm</type>
29+
<boot dev="hd"></boot>
30+
</os>
31+
<features>
32+
<acpi></acpi>
33+
</features>
34+
<on_poweroff>destroy</on_poweroff>
35+
<on_reboot>restart</on_reboot>
36+
<on_crash>restart</on_crash>
37+
<devices>
38+
<emulator>/vmwrapper</emulator>
39+
<disk type="block" device="disk">
40+
<driver name="qemu" type="raw"></driver>
41+
<source dev="/dev/mapper/virtlet-dm-69eec606-0493-5825-73a4-c5e0c0236155"></source>
42+
<target dev="sda" bus="scsi"></target>
43+
<address type="drive" controller="0" bus="0" target="0" unit="0"></address>
44+
</disk>
45+
<disk type="file" device="cdrom">
46+
<driver name="qemu" type="raw"></driver>
47+
<source file="/var/lib/virtlet/config/config-231700d5-c9a6-5a49-738d-99a954c51550.iso"></source>
48+
<target dev="sdb" bus="scsi"></target>
49+
<readonly></readonly>
50+
<address type="drive" controller="0" bus="0" target="0" unit="1"></address>
51+
</disk>
52+
<controller type="scsi" index="0" model="virtio-scsi">
53+
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"></address>
54+
</controller>
55+
<controller type="pci" model="pci-root"></controller>
56+
<serial type="unix">
57+
<source mode="connect" path="/var/lib/libvirt/streamer.sock">
58+
<reconnect enabled="yes" timeout="1"></reconnect>
59+
</source>
60+
<target port="0"></target>
61+
</serial>
62+
<input type="tablet" bus="usb"></input>
63+
<graphics type="vnc" port="-1"></graphics>
64+
<video>
65+
<model type="cirrus"></model>
66+
</video>
67+
</devices>
68+
<commandline xmlns="http://libvirt.org/schemas/domain/qemu/1.0">
69+
<env name="VIRTLET_EMULATOR" value="/usr/bin/kvm"></env>
70+
<env name="VIRTLET_NET_KEY" value="/tmp/fakenetns"></env>
71+
<env name="VIRTLET_CONTAINER_ID" value="231700d5-c9a6-5a49-738d-99a954c51550"></env>
72+
<env name="VIRTLET_CONTAINER_LOG_PATH" value="/var/log/pods/69eec606-0493-5825-73a4-c5e0c0236155/container1_42.log"></env>
73+
</commandline>
74+
</domain>
75+
- name: 'domain conn: virtlet-231700d5-c9a6-container1: Create'
76+
- name: 'domain conn: virtlet-231700d5-c9a6-container1: iso image'
77+
value:
78+
meta-data: '{"instance-id":"testName_0.default","local-hostname":"testName_0"}'
79+
network-config: |
80+
version: 1
81+
user-data: |
82+
#cloud-config
83+
- name: 'domain conn: virtlet-231700d5-c9a6-container1: Destroy'
84+
- name: 'domain conn: virtlet-231700d5-c9a6-container1: Undefine'
85+
- name: CMD
86+
value:
87+
cmd: dmsetup remove virtlet-dm-69eec606-0493-5825-73a4-c5e0c0236155

pkg/libvirttools/TestDomainDefinitions__plain_domain.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__raw_block_volume.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__raw_devices.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__vcpu_count.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__virtio_disk_driver.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainDefinitions__volumes.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-

pkg/libvirttools/TestDomainForcedShutdown.out.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: GetImagePathAndVirtualSize
1+
- name: GetImagePathDigestAndVirtualSize
22
value: fake/image1
33
- name: 'storage: CreateStoragePool'
44
value: |-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- name: setup
2+
- name: 'image: GetImagePathDigestAndVirtualSize'
3+
value: persistent/image1
4+
- name: CMD
5+
value:
6+
cmd: blockdev --getsz /dev/rootdev
7+
stdout: "8"

0 commit comments

Comments
 (0)