Browse Source

first commit

dev v1.0.0
bokuore 2 years ago
commit
d11682f086
  1. 19
      .gitignore
  2. 209
      CHANGELOG.md
  3. 21
      LICENSE
  4. 97
      README.md
  5. 252
      core_service.go
  6. 406
      core_transaction_manager.go
  7. 350
      daemon.go
  8. 51
      src/imageserver/create_disk_image.go
  9. 51
      src/imageserver/create_media_image.go
  10. 36
      src/imageserver/delete_disk_image.go
  11. 37
      src/imageserver/delete_media_image.go
  12. 47
      src/imageserver/get_disk_image.go
  13. 45
      src/imageserver/get_media_image.go
  14. 70
      src/imageserver/handle_disk_image_update.go
  15. 738
      src/imageserver/http_module.go
  16. 930
      src/imageserver/image_manager.go
  17. 134
      src/imageserver/image_service.go
  18. 53
      src/imageserver/modify_disk_image.go
  19. 54
      src/imageserver/modify_media_image.go
  20. 75
      src/imageserver/query_disk_image.go
  21. 66
      src/imageserver/query_media_image.go
  22. 66
      src/imageserver/task_manager.go
  23. 4424
      src/modules/api_module.go
  24. 233
      src/modules/instance.go
  25. 486
      src/modules/module_interface.go
  26. 162
      src/modules/request_proxy.go
  27. 3956
      src/modules/resource_manager.go
  28. 411
      src/modules/restful_data.go
  29. 53
      src/task/add_address_range.go
  30. 124
      src/task/add_compute_cell.go
  31. 48
      src/task/create_address_pool.go
  32. 55
      src/task/create_compute_pool.go
  33. 266
      src/task/create_disk_image.go
  34. 268
      src/task/create_guest.go
  35. 63
      src/task/create_media_image.go
  36. 169
      src/task/create_migration.go
  37. 86
      src/task/create_snapshot.go
  38. 58
      src/task/create_storage_pool.go
  39. 41
      src/task/data_qualifier.go
  40. 40
      src/task/delete_address_pool.go
  41. 39
      src/task/delete_compute_pool.go
  42. 63
      src/task/delete_disk_image.go
  43. 77
      src/task/delete_guest.go
  44. 63
      src/task/delete_media_image.go
  45. 81
      src/task/delete_snapshot.go
  46. 39
      src/task/delete_storage_pool.go
  47. 40
      src/task/disable_compute_cell.go
  48. 76
      src/task/eject_media.go
  49. 42
      src/task/enable_compute_cell.go
  50. 63
      src/task/get_address_pool.go
  51. 61
      src/task/get_address_range.go
  52. 71
      src/task/get_auth.go
  53. 53
      src/task/get_batch_create_guest.go
  54. 52
      src/task/get_batch_delete_guest.go
  55. 51
      src/task/get_batch_stop_guest.go
  56. 93
      src/task/get_compute_cell.go
  57. 58
      src/task/get_compute_cell_status.go
  58. 45
      src/task/get_compute_pool.go
  59. 53
      src/task/get_compute_pool_status.go
  60. 64
      src/task/get_disk_image.go
  61. 45
      src/task/get_guest.go
  62. 78
      src/task/get_instance_status.go
  63. 65
      src/task/get_media_image.go
  64. 46
      src/task/get_migration.go
  65. 82
      src/task/get_snapshot.go
  66. 43
      src/task/get_storage_pool.go
  67. 33
      src/task/handle_address_changed.go
  68. 300
      src/task/handle_cell_available.go
  69. 68
      src/task/handle_cell_disconnected.go
  70. 22
      src/task/handle_cell_status_updated.go
  71. 35
      src/task/handle_guest_created.go
  72. 29
      src/task/handle_guest_deleted.go
  73. 44
      src/task/handle_guest_started.go
  74. 44
      src/task/handle_guest_stopped.go
  75. 32
      src/task/handle_guest_system_reset.go
  76. 64
      src/task/handle_guest_updated.go
  77. 63
      src/task/handle_instance_migrated.go
  78. 56
      src/task/handle_media_attached.go
  79. 51
      src/task/handle_media_detached.go
  80. 97
      src/task/insert_media.go
  81. 64
      src/task/modify_address_pool.go
  82. 89
      src/task/modify_auth.go
  83. 56
      src/task/modify_compute_pool.go
  84. 90
      src/task/modify_core.go
  85. 63
      src/task/modify_disk_image.go
  86. 109
      src/task/modify_guest_disk_threshold.go
  87. 111
      src/task/modify_guest_name.go
  88. 100
      src/task/modify_guest_network_threshold.go
  89. 86
      src/task/modify_guest_priority.go
  90. 63
      src/task/modify_media_image.go
  91. 91
      src/task/modify_memory.go
  92. 59
      src/task/modify_storage_pool.go
  93. 53
      src/task/query_address_pool.go
  94. 52
      src/task/query_address_range.go
  95. 41
      src/task/query_cells_by_pool.go
  96. 85
      src/task/query_compute_cell_status.go
  97. 50
      src/task/query_compute_pool.go
  98. 74
      src/task/query_compute_pool_status.go
  99. 66
      src/task/query_disk_image.go
  100. 96
      src/task/query_guest.go

19
.gitignore

@ -0,0 +1,19 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.idea
log
cert
pkg
config
core

209
CHANGELOG.md

@ -0,0 +1,209 @@
# Change Log
## [1.0.0] - 2019-07-02
### Added
- Set threshold of CPU/Disk IO/Network
- Batch stop guests
- Automatically synchronize the IP address in the TLS certificate when the IP changes
### Changed
- Generate module name base on listen address
- URL of guest operates change from '/guest/' to '/guests/'.
- Guests/Images match with owner or group
## [0.9.1] - 2019-05-16
### Added
- Modify media image
- Get media image
- Query media/disk image filter by owner and group
- Add new API "GET /media_image_search/" for filtering media images by owner and group
### Changed
- Refactor image server
- The image name is unique in a group
- Results of query disk image sorted by name
- Check image and disk size before clone guest
### Fixed
- Accumulate CPU usage to a null value
- Return empty data when querying zone status
- Use wrong CPU usage when computing real cell load
## [0.8.2] - 2019-04-04
### Fixed
- Media image locked when uploading interrupted
## [0.8.1] - 2019-02-15
### Added
- Modify guest name
- Batch creating/deleting guest
### Changed
- Adapt to new runnable implement
- Locate cert files of image server base on the binary path
## [0.7.1] - 2018-12-26
### Added
- System start time when query zone status
- Reset guest system
## [0.6.1] - 2018-11-30
### Added
- Address pool management: query/create/modify/delete
- Address range management: add/remove
- Instance address allocate/migrate
- Allocated address in instance status
## [0.5.1] - 2018-11-3
### Added
- Enable/Disable cell
- Enable failover in compute pool
- Migrate instance
### Changed
- Optimize load balance algorithm considering both real-time load and instances configured when choosing cell for allocation.
- Sort instance list by lexicographic order
## [0.4.2] - 2018-10-10
### Fixed
- result.Error output message
## [0.4.1] - 2018-9-30
### Added
- Storage Pool management: Create/Delete/Modify
- NFS storage backend supported
- Allow choosing storage pool when creating/modifying compute pool
- Synchronize storage configure when cell joined or added
- Add storage mount status when getting cell status
- Check duplicate instance name in a pool when creating a guest
- Mark instance status to lost when cell disconnected
- Notify cell to detach storage when removed from pool
### Fixed
- Improper instance count when instance deallocated
- Task put a message to closed proxy channel causing panic
- Task put a message to deallocated proxy session causing panic
## [0.3.1] - 2018-8-25
### Added
- Insert/Eject media in instance
- Add instance create time
- Add create and modify time of images
- Snapshot management: create/restore/delete/query/get
### Fixed
- Wrong instance name sent to cell when create a new guest
## [0.2.3] - 2018-8-17
### Added
- Support initialize guest after created using Cloud-Init in NoCloudMode
- Enable guest system version/modules configure
- Enable change admin password/create new admin/auto resize&mount disk when ci module enabled(cloud-init cloud-utils required in guest)
- Qualify instance/user/group/image name (only '0~9a~Z-' allowed)
## [0.2.2] - 2018-8-6
### Modify
- Stable sorted result of instance/image/cell/pool list
## [0.2.1] - 2018-7-29
### Added
- Modify Cores/Memory/Disk Size
- Shrink guest volume
- Set/Get user password
- Add "system" property in guest
- Fixed: a newly uploaded disk image cannot use in cloning
## [0.1.3] - 2018-7-24
### Modified
- handle instance address changed event
- API redirect disk image requests
- ignore offline cells when compute score
- forward create disk image request when no target guest specified
- Fixed: instance internal and external address
## [0.1.2] - 2018-7-21
### Modified
- gracefully disconnect when module stop
- add version output on the console

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 project-nano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

97
README.md

@ -0,0 +1,97 @@
# README
## Overview
The Core is the module responsible for managing resources and instances. It embeds an image server that handles media and disk images.
All functions of Nano provide as REST API of the Core, any command or request need process should submit to the Core.
It is also the stub of network discovery, so remember to start the Core before any other modules.
Binary release found [here](<https://github.com/project-nano/releases/releases>)
See more detail for [Quick Guide](<https://nanocloud.readthedocs.io/projects/guide/en/latest/concept.html>)
Official Site: <https://nanos.cloud/en-us/>
REST API: <https://nanoen.docs.apiary.io/>
Wiki: <https://github.com/project-nano/releases/wiki/English>
## Build
Assume that the golang lib installed in the '/home/develop/go', and source code downloaded in the path '/home/develop/nano/core'.
Set environment variable GOPATH before compiling
```
#git clone https://github.com/project-nano/core.git
#cd core
#export GOPATH="/home/develop/go:/home/develop/nano/core"
#go build -o core -i -ldflags="-w -s"
```
## Command Line
All Nano modules provide the command-line interface, and called like :
< module name > [start | stop | status | halt]
- start: start module service, output error message when start failed, or version information.
- stop: stops the service gracefully. Releases allocated resources and notify any related modules.
- status: checks if the module is running.
- halt: terminate service immediately.
You can call the Core module both in the absolute path and relative path.
```
#cd /opt/nano/core
#./core start
or
#/opt/nano/core/core start
```
Please check the log file "log/core.log" when encountering errors.
## Configure
All configure files stores in the path: config
### Domain Configuration
Filename: domain.cfg
See more detail about [Domain](<https://nanocloud.readthedocs.io/projects/guide/en/latest/concept.html#communicate-domain>)
| Parameter | Description |
| ------------------ | ------------------------------------------------------------ |
| **domain** | The name of a communication domain, like 'nano' in default, only allows characters. |
| **group_port** | Multicast port, 5599 in default |
| **group_address** | Multicast address, '224.0.0.226' in default. |
| **listen_address** | Listening Address of the core service,string in the IPv4 format |
### API Configuration
Filename: api.cfg
| Parameter | Description |
| --------- | ------------------------------------------- |
| **port** | listening port of REST API, 5850 in default |
### Image Server Configuration
Filename:image.cfg
| Parameter | Description |
| ------------- | ------------------------------------------------------------ |
| **cert_file** | the file-path of TLS certificate used in image transportation |
| **key_file** | the file-path of TLS key used in image transportation |

252
core_service.go

@ -0,0 +1,252 @@
package main
import (
"github.com/project-nano/framework"
"log"
"modules"
)
const (
CurrentVersion = "1.0.0"
)
type CoreService struct {
framework.EndpointService //base class
ConfigPath string
DataPath string
resourceManager *modules.ResourceManager
transManager *CoreTransactionManager
apiModule *modules.APIModule
}
func (core *CoreService) GetAPIServiceAddress() string{
if nil != core.apiModule{
return core.apiModule.GetServiceAddress()
}
return ""
}
func (core *CoreService)GetVersion() string{
return CurrentVersion
}
func (core *CoreService)OnMessageReceived(msg framework.Message){
if targetSession := msg.GetToSession(); targetSession != 0{
if err := core.transManager.PushMessage(msg);err != nil{
log.Printf("<core> push message [%08X] from %s to session [%08X] fail: %s", msg.GetID(), msg.GetSender(), targetSession, err.Error())
}
return
}
var err error
switch msg.GetID() {
case framework.QueryComputePoolRequest:
case framework.GetComputePoolRequest:
case framework.CreateComputePoolRequest:
case framework.DeleteComputePoolRequest:
case framework.ModifyComputePoolRequest:
case framework.QueryStoragePoolRequest:
case framework.GetStoragePoolRequest:
case framework.CreateStoragePoolRequest:
case framework.DeleteStoragePoolRequest:
case framework.ModifyStoragePoolRequest:
case framework.QueryAddressPoolRequest:
case framework.GetAddressPoolRequest:
case framework.CreateAddressPoolRequest:
case framework.ModifyAddressPoolRequest:
case framework.DeleteAddressPoolRequest:
case framework.QueryAddressRangeRequest:
case framework.GetAddressRangeRequest:
case framework.AddAddressRangeRequest:
case framework.RemoveAddressRangeRequest:
case framework.QueryComputePoolCellRequest:
case framework.GetComputePoolCellRequest:
case framework.AddComputePoolCellRequest:
case framework.RemoveComputePoolCellRequest:
case framework.QueryUnallocatedComputePoolCellRequest:
case framework.QueryZoneStatusRequest:
case framework.QueryComputePoolStatusRequest:
case framework.GetComputePoolStatusRequest:
case framework.QueryComputePoolCellStatusRequest:
case framework.GetComputePoolCellStatusRequest:
case framework.EnableComputePoolCellRequest:
case framework.DisableComputePoolCellRequest:
case framework.MigrateInstanceRequest:
case framework.InstanceMigratedEvent:
case framework.InstancePurgedEvent:
case framework.ComputeCellAvailableEvent:
case framework.ImageServerAvailableEvent:
case framework.QueryGuestRequest:
case framework.GetGuestRequest:
case framework.CreateGuestRequest:
case framework.DeleteGuestRequest:
case framework.ResetSystemRequest:
case framework.QueryInstanceStatusRequest:
case framework.GetInstanceStatusRequest:
case framework.StartInstanceRequest:
case framework.StopInstanceRequest:
case framework.GuestCreatedEvent:
case framework.GuestDeletedEvent:
case framework.GuestStartedEvent:
case framework.GuestStoppedEvent:
case framework.GuestUpdatedEvent:
case framework.CellStatusReportEvent:
case framework.AddressChangedEvent:
case framework.SystemResetEvent:
case framework.StartBatchCreateGuestRequest:
case framework.GetBatchCreateGuestRequest:
case framework.StartBatchDeleteGuestRequest:
case framework.GetBatchDeleteGuestRequest:
case framework.StartBatchStopGuestRequest:
case framework.GetBatchStopGuestRequest:
case framework.ModifyPriorityRequest:
case framework.ModifyDiskThresholdRequest:
case framework.ModifyNetworkThresholdRequest:
case framework.InsertMediaRequest:
case framework.EjectMediaRequest:
case framework.MediaAttachedEvent:
case framework.MediaDetachedEvent:
case framework.ModifyGuestNameRequest:
case framework.ModifyCoreRequest:
case framework.ModifyMemoryRequest:
case framework.ModifyAuthRequest:
case framework.GetAuthRequest:
case framework.ResizeDiskRequest:
case framework.ShrinkDiskRequest:
case framework.QueryDiskImageRequest:
case framework.GetDiskImageRequest:
case framework.CreateDiskImageRequest:
case framework.DeleteDiskImageRequest:
case framework.ModifyDiskImageRequest:
case framework.QueryMediaImageRequest:
case framework.GetMediaImageRequest:
case framework.CreateMediaImageRequest:
case framework.DeleteMediaImageRequest:
case framework.ModifyMediaImageRequest:
case framework.QuerySnapshotRequest:
case framework.GetSnapshotRequest:
case framework.CreateSnapshotRequest:
case framework.DeleteSnapshotRequest:
case framework.RestoreSnapshotRequest:
case framework.SnapshotResumedEvent:
case framework.QueryMigrationRequest:
case framework.GetMigrationRequest:
case framework.CreateMigrationRequest:
case framework.ComputeCellDisconnectedEvent:
default:
core.handleIncomingMessage(msg)
return
}
//Invoke transaction
err = core.transManager.InvokeTask(msg)
if err != nil{
log.Printf("<core> invoke transaction with message [%08X] fail: %s", msg.GetID(), err.Error())
}
}
func (core *CoreService) handleIncomingMessage(msg framework.Message){
switch msg.GetID() {
default:
log.Printf("<core> message [%08X] from %s.[%08X] ignored", msg.GetID(), msg.GetSender(), msg.GetFromSession())
}
}
func (core *CoreService)OnServiceConnected(name string, t framework.ServiceType, remoteAddress string){
log.Printf("<core> service %s connected, type %d", name, t)
switch t {
case framework.ServiceTypeCell:
event, _ := framework.CreateJsonMessage(framework.ComputeCellAvailableEvent)
event.SetString(framework.ParamKeyCell, name)
event.SetString(framework.ParamKeyAddress, remoteAddress)
core.SendToSelf(event)
default:
break
}
}
func (core *CoreService)OnServiceDisconnected(nodeName string, t framework.ServiceType, gracefullyClose bool){
if gracefullyClose{
log.Printf("<core> service %s closed by remote, type %d", nodeName, t)
}else{
log.Printf("<core> service %s lost, type %d", nodeName, t)
}
switch t {
case framework.ServiceTypeCell:
event, _ := framework.CreateJsonMessage(framework.ComputeCellDisconnectedEvent)
event.SetString(framework.ParamKeyCell, nodeName)
event.SetBoolean(framework.ParamKeyFlag, gracefullyClose)
core.SendToSelf(event)
case framework.ServiceTypeImage:
core.resourceManager.RemoveImageServer(nodeName)
default:
break
}
}
func (core *CoreService)OnDependencyReady(){
core.SetServiceReady()
}
func (core *CoreService)InitialEndpoint() (err error){
log.Printf("<core> initial core service, v %s", CurrentVersion)
log.Printf("<core> domain %s, group address %s:%d", core.GetDomain(), core.GetGroupAddress(), core.GetGroupPort())
core.resourceManager, err = modules.CreateResourceManager(core.DataPath)
if err != nil{
return err
}
core.transManager, err = CreateTransactionManager(core, core.resourceManager)
if err != nil{
return err
}
core.apiModule, err = modules.CreateAPIModule(core.ConfigPath, core, core.resourceManager)
if err != nil{
return err
}
//register submodules
if err = core.RegisterSubmodule(core.apiModule.GetModuleName(), core.apiModule.GetResponseChannel());err != nil{
return err
}
return nil
}
func (core *CoreService)OnEndpointStarted() (err error){
if err = core.resourceManager.Start(); err != nil{
return err
}
if err = core.transManager.Start(); err != nil{
return err
}
if err = core.apiModule.Start();err != nil{
return err
}
log.Print("<core> started")
return nil
}
func (core *CoreService)OnEndpointStopped(){
if err := core.apiModule.Stop(); err != nil{
log.Printf("<core> stop api module fail: %s", err.Error())
}
if err := core.transManager.Stop(); err != nil{
log.Printf("<core> stop transaction manager fail: %s", err.Error())
}
if err := core.resourceManager.Stop(); err != nil{
log.Printf("<core> stop compute pool module fail: %s", err.Error())
}
log.Print("<core> stopped")
}

406
core_transaction_manager.go

@ -0,0 +1,406 @@
package main
import (
"github.com/project-nano/framework"
"task"
"modules"
"net/http"
"crypto/tls"
)
type CoreTransactionManager struct {
*framework.TransactionEngine
}
func CreateTransactionManager(sender framework.MessageSender, resourceModule modules.ResourceModule) (*CoreTransactionManager, error) {
engine, err := framework.CreateTransactionEngine()
if err != nil{
return nil, err
}
client := &http.Client{
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
}
var manager = CoreTransactionManager{engine}
if err = manager.RegisterExecutor(framework.QueryComputePoolRequest,
&task.QueryComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetComputePoolRequest,
&task.GetComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateComputePoolRequest,
&task.CreateComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyComputePoolRequest,
&task.ModifyComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteComputePoolRequest,
&task.DeleteComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
//storage pools
if err = manager.RegisterExecutor(framework.QueryStoragePoolRequest,
&task.QueryStoragePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetStoragePoolRequest,
&task.GetStoragePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateStoragePoolRequest,
&task.CreateStoragePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyStoragePoolRequest,
&task.ModifyStoragePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteStoragePoolRequest,
&task.DeleteStoragePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
//address pool&range
if err = manager.RegisterExecutor(framework.QueryAddressPoolRequest,
&task.QueryAddressPoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetAddressPoolRequest,
&task.GetAddressPoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateAddressPoolRequest,
&task.CreateAddressPoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyAddressPoolRequest,
&task.ModifyAddressPoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteAddressPoolRequest,
&task.DeleteAddressPoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryAddressRangeRequest,
&task.QueryAddressRangeExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetAddressRangeRequest,
&task.GetAddressRangeExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.AddAddressRangeRequest,
&task.AddAddressRangeExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.RemoveAddressRangeRequest,
&task.RemoveAddressRangeExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryComputePoolCellRequest,
&task.QueryCellsByPoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetComputePoolCellRequest,
&task.GetComputeCellExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.AddComputePoolCellRequest,
&task.AddComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.RemoveComputePoolCellRequest,
&task.RemoveComputePoolExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryUnallocatedComputePoolCellRequest,
&task.QueryUnallocatedCellsExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryZoneStatusRequest,
&task.QueryZoneStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryComputePoolStatusRequest,
&task.QueryComputePoolStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetComputePoolStatusRequest,
&task.GetComputePoolStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryComputePoolCellStatusRequest,
&task.QueryComputeCellStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetComputePoolCellStatusRequest,
&task.GetComputeCellStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.EnableComputePoolCellRequest,
&task.EnableComputeCellExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DisableComputePoolCellRequest,
&task.DisableComputeCellExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ComputeCellAvailableEvent,
&task.HandleCellAvailableExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetGuestRequest,
&task.GetGuestConfigExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryGuestRequest,
&task.QueryGuestConfigExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateGuestRequest,
&task.CreateGuestExecutor{sender, resourceModule, client}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteGuestRequest,
&task.DeleteGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyGuestNameRequest,
&task.ModifyGuestNameExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyCoreRequest,
&task.ModifyGuestCoreExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyMemoryRequest,
&task.ModifyGuestMemoryExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyPriorityRequest,
&task.ModifyGuestPriorityExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyNetworkThresholdRequest,
&task.ModifyGuestNetworkThresholdExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyDiskThresholdRequest,
&task.ModifyGuestDiskThresholdExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ResizeDiskRequest,
&task.ResizeGuestDiskExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ShrinkDiskRequest,
&task.ShrinkGuestDiskExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ResetSystemRequest,
&task.ResetGuestSystemExecutor{sender, resourceModule, client}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyAuthRequest,
&task.ModifyGuestPasswordExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetAuthRequest,
&task.GetGuestPasswordExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetInstanceStatusRequest,
&task.GetInstanceStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryInstanceStatusRequest,
&task.QueryInstanceStatusExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.StartInstanceRequest,
&task.StartInstanceExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.StopInstanceRequest,
&task.StopInstanceExecutor{sender, resourceModule}); err != nil{
return nil, err
}
//media images
if err = manager.RegisterExecutor(framework.QueryMediaImageRequest,
&task.QueryMediaImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetMediaImageRequest,
&task.GetMediaImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateMediaImageRequest,
&task.CreateMediaImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyMediaImageRequest,
&task.ModifyMediaImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteMediaImageRequest,
&task.DeleteMediaImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
//disk images
if err = manager.RegisterExecutor(framework.QueryDiskImageRequest,
&task.QueryDiskImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetDiskImageRequest,
&task.GetDiskImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateDiskImageRequest,
&task.CreateDiskImageExecutor{sender, resourceModule, client}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ModifyDiskImageRequest,
&task.ModifyDiskImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteDiskImageRequest,
&task.DeleteDiskImageExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GuestCreatedEvent,
&task.HandleGuestCreatedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GuestDeletedEvent,
&task.HandleGuestDeletedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GuestStartedEvent,
&task.HandleGuestStartedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GuestStoppedEvent,
&task.HandleGuestStoppedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GuestUpdatedEvent,
&task.HandleGuestUpdatedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.SystemResetEvent,
&task.HandleGuestSystemResetExecutor{resourceModule}); err != nil{
return nil, err
}
//batch
if err = manager.RegisterExecutor(framework.StartBatchCreateGuestRequest,
&task.StartBatchCreateGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetBatchCreateGuestRequest,
&task.GetBatchCreateGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.StartBatchDeleteGuestRequest,
&task.StartBatchDeleteGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetBatchDeleteGuestRequest,
&task.GetBatchDeleteGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.StartBatchStopGuestRequest,
&task.StartBatchStopGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetBatchStopGuestRequest,
&task.GetBatchStopGuestExecutor{sender, resourceModule}); err != nil{
return nil, err
}
//instance media
if err = manager.RegisterExecutor(framework.InsertMediaRequest,
&task.InsertMediaExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.EjectMediaRequest,
&task.EjectMediaExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.MediaAttachedEvent,
&task.HandleMediaAttachedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.MediaDetachedEvent,
&task.HandleMediaDetachedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
//snapshot
if err = manager.RegisterExecutor(framework.QuerySnapshotRequest,
&task.QuerySnapshotExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetSnapshotRequest,
&task.GetSnapshotExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateSnapshotRequest,
&task.CreateSnapshotExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.DeleteSnapshotRequest,
&task.DeleteSnapshotExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.RestoreSnapshotRequest,
&task.RestoreSnapshotExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.QueryMigrationRequest,
&task.QueryMigrationExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.GetMigrationRequest,
&task.GetMigrationExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CreateMigrationRequest,
&task.CreateMigrationExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.InstanceMigratedEvent,
&task.HandleInstanceMigratedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.CellStatusReportEvent,
&task.HandleCellStatusUpdatedExecutor{resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.AddressChangedEvent,
&task.HandleAddressChangedExecutor{resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ComputeCellDisconnectedEvent,
&task.HandleCellDisconnectedExecutor{sender, resourceModule}); err != nil{
return nil, err
}
if err = manager.RegisterExecutor(framework.ImageServerAvailableEvent,
&task.SyncImageServerExecutor{sender, resourceModule, client}); err != nil{
return nil, err
}
return &manager, nil
}

350
daemon.go

@ -0,0 +1,350 @@
package main
import (
"fmt"
"errors"
"encoding/json"
"path/filepath"
"os"
"log"
"github.com/project-nano/framework"
"io/ioutil"
"github.com/project-nano/sonar"
"modules"
"imageserver"
"crypto/tls"
"crypto/x509"
"math/big"
"crypto/x509/pkix"
"time"
"crypto/rsa"
"encoding/pem"
"net"
"crypto/rand"
)
type DomainConfig struct {
Domain string `json:"domain"`
GroupAddress string `json:"group_address"`
GroupPort int `json:"group_port"`
ListenAddress string `json:"listen_address"`
}
type MainService struct {
core *CoreService
image *imageserver.ImageService
}
const (
ProjectName = "nano"
ExecuteName = "core"
DomainConfigFileName = "domain.cfg"
APIConfigFilename = "api.cfg"
ImageConfigFilename = "image.cfg"
ConfigPathName = "config"
DataPathName = "data"
DefaultPathPerm = 0740
DefaultFilePerm = 0640
)
func (service *MainService)Start() (output string, err error){
if nil == service.core {
err = errors.New("invalid service")
return
}
if err = service.core.Start();err != nil{
return
}
if err = service.image.Start(); err != nil{
return
}
cert, key := service.image.GetTLSFilePath()
output = fmt.Sprintf("\nCore Module %s\nservice %s listen at '%s:%d'\ngroup '%s:%d', domain '%s'\nAPI address '%s', image service '%s'\nImage TLS Cert '%s', Key '%s'",
service.core.GetVersion(),
service.core.GetName(), service.core.GetListenAddress(), service.core.GetListenPort(),
service.core.GetGroupAddress(), service.core.GetGroupPort(), service.core.GetDomain(),
service.core.GetAPIServiceAddress(), service.image.GetImageServiceAddress(),
cert, key)
return
}
func (service *MainService)Stop() (output string, err error){
if nil == service.core {
err = errors.New("invalid service")
return
}
if err = service.image.Stop(); err != nil{
return
}
if err = service.core.Stop(); err != nil{
return
}
return
}
func createDaemon(workingPath string) (service framework.DaemonizedService, err error){
var configPath = filepath.Join(workingPath, ConfigPathName)
var configFile = filepath.Join(configPath, DomainConfigFileName)
data, err := ioutil.ReadFile(configFile)
if err != nil {
return
}
var config DomainConfig
err = json.Unmarshal(data, &config)
if err != nil {
return
}
var dataPath = filepath.Join(workingPath, DataPathName)
if _, err = os.Stat(dataPath);os.IsNotExist(err){
if err = os.Mkdir(dataPath, DefaultPathPerm);err != nil{
return
}else{
log.Printf("data path '%s' created", dataPath)
}
}
var inf *net.Interface
inf, err = framework.InterfaceByAddress(config.ListenAddress)
if err != nil{
return
}
endpointCore, err := framework.CreateStubEndpoint(config.GroupAddress, config.GroupPort, config.Domain, config.ListenAddress)
if err != nil {
return
}
var s = MainService{}
s.core = &CoreService{EndpointService: endpointCore, ConfigPath: configPath, DataPath: dataPath}
s.core.RegisterHandler(s.core)
err = s.core.GenerateName(framework.ServiceTypeCore, inf)
if err != nil{
return
}
endpointImage, err := framework.CreatePeerEndpoint(config.GroupAddress, config.GroupPort, config.Domain)
if err != nil{
return
}
s.image = &imageserver.ImageService{EndpointService: endpointImage, ConfigPath: configPath, DataPath: dataPath}
s.image.RegisterHandler(s.image)
if err = s.image.GenerateName(framework.ServiceTypeImage, inf); err != nil{
return
}
return &s, nil
}
func main() {
framework.ProcessDaemon(ExecuteName, generateConfigure, createDaemon)
}
func generateConfigure(workingPath string) (err error) {
var configPath= filepath.Join(workingPath, ConfigPathName)
if _, err = os.Stat(configPath); os.IsNotExist(err) {
//create path
err = os.Mkdir(configPath, DefaultPathPerm)
if err != nil {
return
}
fmt.Printf("config path %s created\n", configPath)
}
if err = generateDomainConfig(configPath); err != nil{
return
}
if err = generateAPIConfig(configPath); err != nil{
return
}
if err = generateImageConfig(workingPath, configPath); err != nil{
return
}
return
}
func generateDomainConfig(configPath string) (err error) {
var configFile = filepath.Join(configPath, DomainConfigFileName)
if _, err = os.Stat(configFile); os.IsNotExist(err) {
fmt.Println("No domain config available, following instructions to generate a new one.")
var config = DomainConfig{}
if config.Domain, err = framework.InputString("Group Domain Name", sonar.DefaultDomain); err != nil{
return
}
if config.GroupAddress, err = framework.InputMultiCastAddress("Group MultiCast Address", sonar.DefaultMulticastAddress); err != nil{
return
}
if config.GroupPort, err = framework.InputNetworkPort("Group MultiCast Port", sonar.DefaultMulticastPort);err !=nil{
return
}
if config.ListenAddress, err = framework.ChooseIPV4Address("Listen Address"); err != nil{
return
}
//write
var data []byte
data, err = json.MarshalIndent(config, "", " ")
if err != nil {
return
}
if err = ioutil.WriteFile(configFile, data, DefaultFilePerm); err != nil {
return
}
fmt.Printf("domain configure '%s' generated\n", configFile)
}
return
}
func generateAPIConfig(configPath string) (err error) {
const (
DefaultAPIServePort = 5850
)
var configFile = filepath.Join(configPath, APIConfigFilename)
if _, err = os.Stat(configFile); os.IsNotExist(err) {
fmt.Println("No API config available, following instructions to generate a new one.")
var config = modules.APIConfig{}
if config.Port, err = framework.InputInteger("API Serve Port", DefaultAPIServePort);err !=nil{
return
}
//write
var data []byte
data, err = json.MarshalIndent(config, "", " ")
if err != nil {
return
}
if err = ioutil.WriteFile(configFile, data, DefaultFilePerm); err != nil {
return
}
fmt.Printf("api configure '%s' generated\n", configFile)
}
return
}
func generateImageConfig(workingPath, configPath string) (err error) {
const (
RootPath = "/opt"
CertPathName = "cert"
)
//cert file
var certFileName = fmt.Sprintf("%s_image.crt.pem", ProjectName)
var keyFileName = fmt.Sprintf("%s_image.key.pem", ProjectName)
var generatedCertFile = filepath.Join(workingPath, CertPathName, certFileName)
var generatedKeyFile = filepath.Join(workingPath, CertPathName, keyFileName)
if _, err = os.Stat(generatedCertFile);os.IsNotExist(err){
fmt.Println("No cert file available, following instructions to generate a new one.")
var certPath = filepath.Join(workingPath, CertPathName)
//generate new cert & key pair
if _, err = os.Stat(certPath);os.IsNotExist(err){
if err = os.Mkdir(certPath, DefaultPathPerm);err != nil{
return
}else{
fmt.Printf("cert path '%s' created\n", certPath)
}
}
var defaultRootCertPath = filepath.Join(RootPath, ProjectName, CertPathName)
var rootCertPath string
if rootCertPath, err = framework.InputString("Root Cert File Location", defaultRootCertPath); err != nil{
return
}
var rootCertFile = filepath.Join(rootCertPath, fmt.Sprintf("%s_ca.crt.pem", ProjectName))
var rootKeyFile = filepath.Join(rootCertPath, fmt.Sprintf("%s_ca.key.pem", ProjectName))
if _, err = os.Stat(rootCertFile);os.IsNotExist(err){
return
}
if _, err = os.Stat(rootKeyFile);os.IsNotExist(err){
return
}
var localAddress string
if localAddress, err = framework.ChooseIPV4Address("Image Server Address");err != nil{
return
}
if err = signImageCertificate(rootCertFile, rootKeyFile, localAddress, generatedCertFile, generatedKeyFile);err != nil{
return
}
}
var configFile = filepath.Join(configPath, ImageConfigFilename)
if _, err = os.Stat(configFile); os.IsNotExist(err) {
var config = imageserver.ImageServiceConfig{generatedCertFile, generatedKeyFile}
//write
var data []byte
data, err = json.MarshalIndent(config, "", " ")
if err != nil {
return
}
if err = ioutil.WriteFile(configFile, data, DefaultFilePerm); err != nil {
return
}
fmt.Printf("image configure '%s' generated\n", configFile)
}
return
}
func signImageCertificate(caCert, caKey, localAddress, certPath, keyPath string) (err error){
const (
RSAKeyBits = 2048
DefaultDurationYears = 99
)
rootPair, err := tls.LoadX509KeyPair(caCert, caKey)
if err != nil{
return
}
rootCA, err := x509.ParseCertificate(rootPair.Certificate[0])
if err != nil{
return err
}
var serialNumber = big.NewInt(1700)
var imageCert = x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: fmt.Sprintf("%s ImageServer", ProjectName),
Organization: []string{ProjectName},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(DefaultDurationYears, 0, 0),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment|x509.KeyUsageDataEncipherment,
IPAddresses: []net.IP{net.ParseIP(localAddress)},
}
var imagePrivate *rsa.PrivateKey
imagePrivate, err = rsa.GenerateKey(rand.Reader, RSAKeyBits)
if err != nil {
return
}
fmt.Printf("private key with %d bits generated\n", RSAKeyBits)
var imagePublic = imagePrivate.PublicKey
var certContent []byte
certContent, err = x509.CreateCertificate(rand.Reader, &imageCert, rootCA, &imagePublic, rootPair.PrivateKey)
if err != nil {
return
}
// Public key
var certFile *os.File
certFile, err = os.Create(certPath)
if err != nil {
return
}
if err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certContent}); err != nil {
return
}
if err = certFile.Close(); err != nil {
return
}
fmt.Printf("cert file '%s' generated\n", certPath)
// Private key
var keyFile *os.File
keyFile, err = os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, DefaultFilePerm)
if err != nil {
os.Remove(certPath)
return
}
if err = pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(imagePrivate)}); err != nil {
os.Remove(certPath)
return
}
if err = keyFile.Close(); err != nil {
os.Remove(certPath)
return
}
fmt.Printf("key file '%s' generated\n", keyPath)
return nil
}

51
src/imageserver/create_disk_image.go

@ -0,0 +1,51 @@
package imageserver
import (
"github.com/project-nano/framework"
"log"
)
type CreateDiskImageExecutor struct {
Sender framework.MessageSender
ImageServer *ImageManager
}
func (executor *CreateDiskImageExecutor)Execute(id framework.SessionID, request framework.Message,
incoming chan framework.Message, terminate chan bool) (err error) {
var config DiskConfig
if config.Name, err = request.GetString(framework.ParamKeyName); err != nil {
return err
}
if config.Owner, err = request.GetString(framework.ParamKeyUser); err != nil {
return err
}
if config.Group, err = request.GetString(framework.ParamKeyGroup); err != nil {
return err
}
if config.Description, err = request.GetString(framework.ParamKeyDescription); err != nil {
return err
}
if config.Tags, err = request.GetStringArray(framework.ParamKeyTag); err != nil {
return err
}
var respChan = make(chan ImageResult, 1)
executor.ImageServer.CreateDiskImage(config, respChan)
result := <- respChan
resp, _ := framework.CreateJsonMessage(framework.CreateDiskImageResponse)
resp.SetSuccess(false)
resp.SetFromSession(id)
resp.SetToSession(request.GetFromSession())
if result.Error != nil{
err = result.Error
resp.SetError(err.Error())
log.Printf("[%08X] create disk image fail: %s", id, err.Error())
return executor.Sender.SendMessage(resp, request.GetSender())
}
log.Printf("[%08X] new disk image '%s' created(id '%s')", id, config.Name, result.ID)
resp.SetString(framework.ParamKeyImage, result.ID)
resp.SetSuccess(true)
return executor.Sender.SendMessage(resp, request.GetSender())
}

51
src/imageserver/create_media_image.go

@ -0,0 +1,51 @@
package imageserver
import (
"github.com/project-nano/framework"
"log"
)
type CreateMediaImageExecutor struct {
Sender framework.MessageSender
ImageServer *ImageManager
}
func (executor *CreateMediaImageExecutor)Execute(id framework.SessionID, request framework.Message,
incoming chan framework.Message, terminate chan bool) (err error) {
var config MediaConfig
if config.Name, err = request.GetString(framework.ParamKeyName); err != nil {
return err
}
if config.Owner, err = request.GetString(framework.ParamKeyUser); err != nil {
return err
}
if config.Group, err = request.GetString(framework.ParamKeyGroup); err != nil {
return err
}
if config.Description, err = request.GetString(framework.ParamKeyDescription); err != nil {
return err
}
if config.Tags, err = request.GetStringArray(framework.ParamKeyTag); err != nil {
return err
}
var respChan = make(chan ImageResult, 1)
executor.ImageServer.CreateMediaImage(config, respChan)
result := <- respChan
resp, _ := framework.CreateJsonMessage(framework.CreateMediaImageResponse)
resp.SetSuccess(false)
resp.SetFromSession(id)
resp.SetToSession(request.GetFromSession())
if result.Error != nil{
err = result.Error
resp.SetError(err.Error())
log.Printf("[%08X] create media image fail: %s", id, err.Error())
return executor.Sender.SendMessage(resp, request.GetSender())
}
log.Printf("[%08X] new media image '%s' created(id '%s')", id, config.Name, result.ID)
resp.SetString(framework.ParamKeyImage, result.ID)
resp.SetSuccess(true)
return executor.Sender.SendMessage(resp, request.GetSender())
}

36
src/imageserver/delete_disk_image.go

@ -0,0 +1,36 @@
package imageserver
import (
"github.com/project-nano/framework"
"log"
)
type DeleteDiskImageExecutor struct {
Sender framework.MessageSender
ImageServer *ImageManager
}
func (executor *DeleteDiskImageExecutor)Execute(id framework.SessionID, request framework.Message,
incoming chan framework.Message, terminate chan bool) (err error) {
imageID, err := request.GetString(framework.ParamKeyImage)
if err != nil{
return err
}
resp, _ := framework.CreateJsonMessage(framework.DeleteDiskImageResponse)
resp.SetSuccess(false)
resp.SetFromSession(id)
resp.SetToSession(request.GetFromSession())
var respChan = make(chan error, 1)
executor.ImageServer.DeleteDiskImage(imageID, respChan)
err = <-respChan
if err != nil {
resp.SetError(err.Error())
log.Printf("[%08X] delete disk image fail: %s", id, err.Error())
return executor.Sender.SendMessage(resp, request.GetSender())
}
resp.SetSuccess(true)
log.Printf("[%08X] disk image '%s' deleted", id, imageID)
return executor.Sender.SendMessage(resp, request.GetSender())
}

37
src/imageserver/delete_media_image.go

@ -0,0 +1,37 @@
package imageserver
import (
"github.com/project-nano/framework"
"log"
)
type DeleteMediaImageExecutor struct {
Sender framework.MessageSender
ImageServer *ImageManager
}
func (executor *DeleteMediaImageExecutor)Execute(id framework.SessionID, request framework.Message,
incoming chan framework.Message, terminate chan bool) (err error) {
imageID, err := request.GetString(framework.ParamKeyImage)
if err != nil{
return err
}
resp, _ := framework.CreateJsonMessage(framework.DeleteMediaImageResponse)
resp.SetSuccess(false)
resp.SetFromSession(id)
resp.SetToSession(request.GetFromSession())
var respChan = make(chan error, 1)
executor.ImageServer.DeleteMediaImage(imageID, respChan)
err = <- respChan
if err != nil{
resp.SetError(err.Error())
log.Printf("[%08X] delete media image fail: %s", id, err.Error())
return executor.Sender.SendMessage(resp, request.GetSender())
}
//deallocated
resp.SetSuccess(true)
log.Printf("[%08X] media image '%s' deleted", id, imageID)
return executor.Sender.SendMessage(resp, request.GetSender())
}

47
src/imageserver/get_disk_image.go

@ -0,0 +1,47 @@
package imageserver