yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/esxi/storagecache.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package esxi 16 17 import ( 18 "context" 19 "fmt" 20 "path" 21 "regexp" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/log" 25 "yunion.io/x/pkg/errors" 26 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/onecloud/pkg/mcclient" 29 "yunion.io/x/cloudmux/pkg/multicloud" 30 ) 31 32 const ( 33 IMAGE_CACHE_DIR_NAME = "image_cache" 34 ) 35 36 type SDatastoreImageCache struct { 37 multicloud.SResourceBase 38 multicloud.STagBase 39 datastore *SDatastore 40 host *SHost 41 } 42 43 type EsxiOptions struct { 44 ReasonableCIDREsxi string `help:"Reasonable CIDR in esxi, such as '10.0.0.0/8'" defautl:""` 45 TemplateNameRegex string `help:"Regex of template name"` 46 } 47 48 var tempalteNameRegex *regexp.Regexp 49 50 func InitEsxiConfig(opt EsxiOptions) error { 51 var err error 52 if len(opt.TemplateNameRegex) != 0 { 53 tempalteNameRegex, err = regexp.Compile(opt.TemplateNameRegex) 54 if err != nil { 55 return errors.Wrap(err, "regexp.Compile") 56 } 57 } 58 return initVMIPV4Filter(opt.ReasonableCIDREsxi) 59 } 60 61 func (self *SDatastoreImageCache) GetId() string { 62 if self.host != nil { 63 return self.host.GetGlobalId() 64 } else { 65 return self.datastore.GetGlobalId() 66 } 67 } 68 69 func (self *SDatastoreImageCache) GetName() string { 70 if self.host != nil { 71 return fmt.Sprintf("storage-cache-%s", self.host.GetName()) 72 } else { 73 return fmt.Sprintf("storage-cache-%s", self.datastore.GetName()) 74 } 75 } 76 77 func (self *SDatastoreImageCache) GetGlobalId() string { 78 return self.GetId() 79 } 80 81 func (self *SDatastoreImageCache) GetStatus() string { 82 return "available" 83 } 84 85 func (self *SDatastoreImageCache) Refresh() error { 86 return nil 87 } 88 89 func (self *SDatastoreImageCache) IsEmulated() bool { 90 return false 91 } 92 93 func (self *SDatastoreImageCache) GetPath() string { 94 return path.Join(self.datastore.GetMountPoint(), IMAGE_CACHE_DIR_NAME) 95 } 96 97 func (self *SDatastoreImageCache) getTempalteVMs() ([]*SVirtualMachine, error) { 98 return self.datastore.FetchTemplateVMs() 99 } 100 101 func (self *SDatastoreImageCache) getFakeTempateVMs() ([]*SVirtualMachine, error) { 102 if tempalteNameRegex == nil { 103 return nil, nil 104 } 105 return self.datastore.FetchFakeTempateVMs("") 106 } 107 108 func (self *SDatastoreImageCache) GetIImageInImagecache() ([]cloudprovider.ICloudImage, error) { 109 ctx := context.Background() 110 ret := make([]cloudprovider.ICloudImage, 0, 2) 111 files, err := self.datastore.ListDir(ctx, IMAGE_CACHE_DIR_NAME) 112 if errors.Cause(err) == errors.ErrNotFound { 113 return ret, nil 114 } 115 if err != nil { 116 log.Errorf("GetIImages ListDir fail %s", err) 117 return ret, nil 118 } 119 120 validFilenames := make(map[string]bool) 121 122 for i := 0; i < len(files); i += 1 { 123 filename := path.Join(IMAGE_CACHE_DIR_NAME, files[i].Name) 124 if err := self.datastore.CheckVmdk(ctx, filename); err != nil { 125 continue 126 } 127 vmdkInfo, err := self.datastore.GetVmdkInfo(ctx, filename) 128 if err != nil { 129 continue 130 } 131 image := SImage{ 132 cache: self, 133 filename: filename, 134 size: vmdkInfo.Size(), 135 createAt: files[i].Date, 136 } 137 ret = append(ret, &image) 138 vmdkName := files[i].Name 139 vmdkExtName := fmt.Sprintf("%s-flat.vmdk", vmdkName[:len(vmdkName)-5]) 140 validFilenames[vmdkName] = true 141 validFilenames[vmdkExtName] = true 142 } 143 144 log.Debugf("storage cache contains %#v", validFilenames) 145 // cleanup storage cache!!! 146 for i := 0; i < len(files); i += 1 { 147 if _, ok := validFilenames[files[i].Name]; !ok { 148 log.Debugf("delete invalid vmdk file %s!!!", files[i].Name) 149 self.datastore.Delete(ctx, path.Join(IMAGE_CACHE_DIR_NAME, files[i].Name)) 150 } 151 } 152 153 return ret, nil 154 } 155 156 var ErrTimeConsuming = errors.Error("time consuming") 157 158 func (self *SDatastoreImageCache) getTemplateVMsFromCache() ([]*SVirtualMachine, error) { 159 ihosts, err := self.datastore.datacenter.GetIHosts() 160 if err != nil { 161 return nil, err 162 } 163 dsRef := self.datastore.getDatastore().Self 164 ret := make([]*SVirtualMachine, 0) 165 for i := range ihosts { 166 tvms := ihosts[i].(*SHost).tempalteVMs 167 if tvms == nil { 168 return nil, ErrTimeConsuming 169 } 170 for _, vm := range tvms { 171 dss := vm.getVirtualMachine().Datastore 172 for _, ds := range dss { 173 if ds == dsRef { 174 ret = append(ret, vm) 175 break 176 } 177 } 178 } 179 } 180 return ret, nil 181 } 182 183 func (self *SDatastoreImageCache) GetIImageInTemplateVMs() ([]cloudprovider.ICloudImage, error) { 184 ret := make([]cloudprovider.ICloudImage, 0, 2) 185 log.Infof("start to GetIImages") 186 187 datastore := self.datastore 188 if datastore.datacenter.ihosts != nil { 189 vms, err := self.getTemplateVMsFromCache() 190 if err == nil { 191 for i := range vms { 192 ret = append(ret, NewVMTemplate(vms[i], self)) 193 } 194 return ret, nil 195 } 196 } 197 realTemplates, err := self.getTempalteVMs() 198 if err != nil { 199 return nil, errors.Wrap(err, "getTemplateVMs") 200 } 201 fakeTemplates, err := self.getFakeTempateVMs() 202 if err != nil { 203 return nil, errors.Wrap(err, "getFakeTempateVMs") 204 } 205 206 for i := range realTemplates { 207 ret = append(ret, NewVMTemplate(realTemplates[i], self)) 208 } 209 for i := range fakeTemplates { 210 ret = append(ret, NewVMTemplate(fakeTemplates[i], self)) 211 } 212 213 log.Infof("get templates successfully") 214 log.Debugf("fake template name: ") 215 for i := range fakeTemplates { 216 log.Debugf("%s ", fakeTemplates[i].GetName()) 217 } 218 log.Debugf("real template name: ") 219 for i := range realTemplates { 220 log.Debugf("%s ", realTemplates[i].GetName()) 221 } 222 return ret, nil 223 } 224 225 func (self *SDatastoreImageCache) GetIImageInTemplateVMsById(id string) (cloudprovider.ICloudImage, error) { 226 if tempalteNameRegex != nil { 227 vm, err := self.datastore.FetchFakeTempateVMById(id, "") 228 log.Infof("FetchFakeTempateVMById: %v, %v", vm, err) 229 if err == nil { 230 return NewVMTemplate(vm, self), nil 231 } 232 if errors.Cause(err) != errors.ErrNotFound { 233 return nil, err 234 } 235 } 236 vm, err := self.datastore.FetchTemplateVMById(id) 237 if err == nil { 238 return NewVMTemplate(vm, self), nil 239 } 240 return nil, err 241 } 242 243 func (self *SDatastoreImageCache) GetICustomizedCloudImages() ([]cloudprovider.ICloudImage, error) { 244 return nil, cloudprovider.ErrNotImplemented 245 } 246 247 func (self *SDatastoreImageCache) GetICloudImages() ([]cloudprovider.ICloudImage, error) { 248 images1, err := self.GetIImageInTemplateVMs() 249 if err != nil { 250 return nil, err 251 } 252 return images1, nil 253 // images2, err := self.GetIImageInImagecache() 254 // if err != nil { 255 // return nil, err 256 // } 257 // return append(images1, images2...), nil 258 } 259 260 func (self *SDatastoreImageCache) GetIImageById(extId string) (cloudprovider.ICloudImage, error) { 261 // check templatevms 262 image, err := self.GetIImageInTemplateVMsById(extId) 263 if err == nil { 264 return image, nil 265 } 266 if errors.Cause(err) != errors.ErrNotFound { 267 return nil, err 268 } 269 log.Infof("start to GetIImageInImagecache") 270 images, err := self.GetIImageInImagecache() 271 if err != nil { 272 return nil, err 273 } 274 for i := 0; i < len(images); i += 1 { 275 if images[i].GetGlobalId() == extId { 276 return images[i], nil 277 } 278 } 279 return nil, cloudprovider.ErrNotFound 280 } 281 282 func (self *SDatastoreImageCache) CreateIImage(snapshotId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) { 283 return nil, cloudprovider.ErrNotImplemented 284 } 285 286 func (self *SDatastoreImageCache) DownloadImage(userCred mcclient.TokenCredential, imageId string, extId string, path string) (jsonutils.JSONObject, error) { 287 return nil, cloudprovider.ErrNotImplemented 288 } 289 290 func (self *SDatastoreImageCache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, image *cloudprovider.SImageCreateOption, callback func(progress float32)) (string, error) { 291 return "", cloudprovider.ErrNotImplemented 292 }