This repository has been archived by the owner on Jul 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 51
/
types.go
856 lines (727 loc) · 28 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
/*
// Copyright (c) 2016 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package types
import (
"encoding/json"
"errors"
"strconv"
"strings"
"sync"
"time"
"github.com/ciao-project/ciao/ciao-storage"
"github.com/ciao-project/ciao/payloads"
"github.com/ciao-project/ciao/ssntp"
"github.com/golang/glog"
)
// SourceType contains the valid values of the storage source.
type SourceType string
const (
// ImageService indicates the source comes from the image service.
ImageService SourceType = "image"
// VolumeService indicates the source comes from the volume service.
VolumeService SourceType = "volume"
// Empty indicates that there is no source for the storage source
Empty SourceType = "empty"
)
// StorageResource defines a storage resource for a workload.
// TBD: should the workload support multiple of these?
type StorageResource struct {
// ID indicates a volumeID. If ID is blank, then it needs to be created.
ID string `json:"id"`
// Bootable indicates whether should the resource be used for booting
Bootable bool `json:"bootable"`
// Ephemeral indicates whether the storage is temporary
// TBD: do we bother to save info about temp storage?
// does it count against quota?
Ephemeral bool `json:"ephemeral"`
// Size is the size of the storage to be created if new.
Size int `json:"size"`
// ImageType indicates whether we are making a new resource
// based on an image or existing volume.
// Needed only for new storage.
SourceType SourceType `json:"source_type"`
// Source represents the ID or name of either the image or the volume
// that the storage resource is based on.
Source string `json:"source_id"`
// Tag is a piece of abitrary search/sort identifier text
Tag string
// Internal indicates whether this storage should be shown to the user
Internal bool
}
// Workload contains resource and configuration information for a user
// workload.
type Workload struct {
ID string `json:"id"`
TenantID string `json:"-"`
Description string `json:"description"`
FWType string `json:"fw_type"`
VMType payloads.Hypervisor `json:"vm_type"`
ImageName string `json:"image_name"`
Config string `json:"config"`
Storage []StorageResource `json:"storage"`
Visibility Visibility `json:"visibility"`
Requirements payloads.WorkloadRequirements `json:"workload_requirements"`
}
// WorkloadResponse will be returned from /workloads apis
// It provides details on the workload, and references for the client.
type WorkloadResponse struct {
Workload Workload `json:"workload"`
Link Link `json:"link"`
}
// WorkloadRequest contains resource and configuration for a user
// workload.
type WorkloadRequest struct {
WorkloadID string
TenantID string
Instances int
TraceLabel string
Name string
Subnet string
}
// Instance contains information about an instance of a workload.
type Instance struct {
ID string `json:"instance_id"`
TenantID string `json:"tenant_id"`
State string `json:"instance_state"`
WorkloadID string `json:"workload_id"`
NodeID string `json:"node_id"`
MACAddress string `json:"mac_address"`
VnicUUID string `json:"vnic_uuid"`
Subnet string `json:"subnet"`
IPAddress string `json:"ip_address"`
SSHIP string `json:"ssh_ip"`
SSHPort int `json:"ssh_port"`
CNCI bool `json:"-"`
CreateTime time.Time `json:"-"`
Name string `json:"name"`
StateLock sync.RWMutex `json:"-"`
StateChange *sync.Cond `json:"-"`
}
// SortedInstancesByID implements sort.Interface for Instance by ID string
type SortedInstancesByID []*Instance
func (s SortedInstancesByID) Len() int { return len(s) }
func (s SortedInstancesByID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortedInstancesByID) Less(i, j int) bool { return s[i].ID < s[j].ID }
// SortedNodesByID implements sort.Interface for Node by ID string
type SortedNodesByID []CiaoNode
func (s SortedNodesByID) Len() int { return len(s) }
func (s SortedNodesByID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortedNodesByID) Less(i, j int) bool { return s[i].ID < s[j].ID }
// TenantConfig stores the configurable attributes of a tenant.
type TenantConfig struct {
Name string `json:"name"`
SubnetBits int `json:"subnet_bits"`
Permissions struct {
PrivilegedContainers bool `json:"privileged_containers"`
} `json:"permissions"`
}
// Tenant contains information about a tenant or project.
type Tenant struct {
TenantConfig
ID string
CNCIctrl CNCIController
}
// TenantSummary is a short form of Tenant
type TenantSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Links []Link `json:"links,omitempty"`
}
// TenantsListResponse stores a list of tenants retrieved by listTenants
type TenantsListResponse struct {
Tenants []TenantSummary `json:"tenants"`
}
// TenantRequest contains information for creating a new tenant.
type TenantRequest struct {
ID string `json:"id"`
Config TenantConfig `json:"config"`
}
// LogEntry stores information about events.
type LogEntry struct {
Timestamp time.Time `json:"time_stamp"`
TenantID string `json:"tenant_id"`
NodeID string `json:"node_id"`
EventType string `json:"type"`
Message string `json:"message"`
}
// NodeStats stores statistics for individual nodes in the cluster.
type NodeStats struct {
NodeID string `json:"node_id"`
Timestamp time.Time `json:"time_stamp"`
Load int `json:"load"`
MemTotalMB int `json:"mem_total_mb"`
MemAvailableMB int `json:"mem_available_mb"`
DiskTotalMB int `json:"disk_total_mb"`
DiskAvailableMB int `json:"disk_available_mb"`
CpusOnline int `json:"cpus_online"`
}
// NodeSummary contains summary information for all nodes in the cluster.
type NodeSummary struct {
NodeID string `json:"node_id"`
TotalInstances int `json:"total_instances"`
TotalRunningInstances int `json:"total_running_instances"`
TotalPendingInstances int `json:"total_pending_instances"`
TotalPausedInstances int `json:"total_paused_instances"`
TotalFailures int `json:"total_failures"`
}
// TenantCNCI contains information about the CNCI instance for a tenant.
type TenantCNCI struct {
TenantID string `json:"tenant_id"`
IPAddress string `json:"ip_address"`
MACAddress string `json:"mac_address"`
InstanceID string `json:"instance_id"`
Subnets []string `json:"subnets"`
}
// FrameStat contains tracing information per node.
type FrameStat struct {
ID string `json:"node_id"`
TotalElapsedTime float64 `json:"total_elapsed_time"`
ControllerTime float64 `json:"total_controller_time"`
LauncherTime float64 `json:"total_launcher_time"`
SchedulerTime float64 `json:"total_scheduler_time"`
}
// BatchFrameStat contains tracing information for a group of start requests
// by label.
type BatchFrameStat struct {
NumInstances int `json:"num_instances"`
TotalElapsed float64 `json:"total_elapsed"`
AverageElapsed float64 `json:"average_elapsed"`
AverageControllerElapsed float64 `json:"average_controller_elapsed"`
AverageLauncherElapsed float64 `json:"average_launcher_elapsed"`
AverageSchedulerElapsed float64 `json:"average_scheduler_elapsed"`
VarianceController float64 `json:"controller_variance"`
VarianceLauncher float64 `json:"launcher_variance"`
VarianceScheduler float64 `json:"scheduler_variance"`
}
// BatchFrameSummary provides summary information on tracing per label.
type BatchFrameSummary struct {
BatchID string `json:"batch_id"`
NumInstances int `json:"num_instances"`
}
// Node contains information about a physical node in the cluster.
type Node struct {
ID string `json:"node_id"`
IPAddr string `json:"ip_address"`
Hostname string `json:"hostname"`
TotalFailures int `json:"total_failures"`
StartFailures int `json:"start_failures"`
AttachVolumeFailures int `json:"attach_failures"`
DeleteFailures int `json:"delete_failures"`
NodeRole ssntp.Role `json:"role"`
}
// BlockState represents the state of the block device in the controller
// datastore. This is a subset of the openstack status type.
type BlockState string
const (
// Available means that the volume is ok for attaching.
Available BlockState = "available"
// Attaching means that the volume is in the process
// of attaching to an instance.
Attaching BlockState = "attaching"
// InUse means that the volume has been successfully
// attached to an instance.
InUse BlockState = "in-use"
// Detaching means that the volume is in process
// of detaching.
Detaching BlockState = "detaching"
)
// Volume respresents the attributes of this block device.
// TBD - do we really need to store this as actual data,
// or can we use a set of interfaces to get the info?
type Volume struct {
storage.BlockDevice
TenantID string `json:"tenant_id"` // the tenant who owns this volume
State BlockState `json:"state"` // status of
CreateTime time.Time `json:"created"` // when we created the volume
Name string `json:"name"` // a human readable name for this volume
Description string `json:"description"` // some text to describe this volume.
Internal bool `json:"internal"` // whether this storage should be shown to the user
}
// StorageAttachment represents a link between a block device and
// an instance.
type StorageAttachment struct {
ID string // a uuid
InstanceID string // the instance this volume is attached to
BlockID string // the ID of the block device
Ephemeral bool // whether the storage should be deleted on Cleanup
Boot bool // whether this is a boot device
}
// CiaoNode contains status and statistic information for an individual
// node.
type CiaoNode struct {
ID string `json:"id"`
Hostname string `json:"hostname"`
Timestamp time.Time `json:"updated"`
Status string `json:"status"`
MemTotal int `json:"ram_total"`
MemAvailable int `json:"ram_available"`
DiskTotal int `json:"disk_total"`
DiskAvailable int `json:"disk_available"`
Load int `json:"load"`
OnlineCPUs int `json:"online_cpus"`
TotalInstances int `json:"total_instances"`
TotalRunningInstances int `json:"total_running_instances"`
TotalPendingInstances int `json:"total_pending_instances"`
TotalPausedInstances int `json:"total_paused_instances"`
TotalFailures int `json:"total_failures"`
StartFailures int `json:"start_failures"`
AttachVolumeFailures int `json:"attach_failures"`
DeleteFailures int `json:"delete_failures"`
}
// NodeStatusType contains the valid values of a node's status
type NodeStatusType string
const (
// NodeStatusReady indicates that a node is ready to receive start
// requests.
NodeStatusReady NodeStatusType = "READY"
// NodeStatusFull indicates that a node is full and cannot satisfy
// start requests.
NodeStatusFull NodeStatusType = "FULL"
// NodeStatusMaintenance indicates that a node is in maintenance mode
// and cannot satisfy start requests.
NodeStatusMaintenance NodeStatusType = "MAINTENANCE"
)
// CiaoNodeStatus contains status information for an individual node.
type CiaoNodeStatus struct {
Status NodeStatusType `json:"status"`
}
// CiaoNodes represents the unmarshalled version of the contents of a
// /v2.1/nodes response. It contains status and statistics information
// for a set of nodes.
type CiaoNodes struct {
Nodes []CiaoNode `json:"nodes"`
}
// NewCiaoNodes allocates a CiaoNodes structure.
// It allocates the Nodes slice as well so that the marshalled
// JSON is an empty array and not a nil pointer, as specified by the
// OpenStack APIs.
func NewCiaoNodes() (nodes CiaoNodes) {
nodes.Nodes = []CiaoNode{}
return
}
// CiaoTenantResources represents the unmarshalled version of the contents of a
// /v2.1/{tenant}/quotas response. It contains the current resource usage
// information for a tenant.
type CiaoTenantResources struct {
ID string `json:"id"`
Timestamp time.Time `json:"updated"`
InstanceLimit int `json:"instances_limit"`
InstanceUsage int `json:"instances_usage"`
VCPULimit int `json:"cpus_limit"`
VCPUUsage int `json:"cpus_usage"`
MemLimit int `json:"ram_limit"`
MemUsage int `json:"ram_usage"`
DiskLimit int `json:"disk_limit"`
DiskUsage int `json:"disk_usage"`
}
// CiaoUsage contains a snapshot of resource consumption for a tenant.
type CiaoUsage struct {
VCPU int `json:"cpus_usage"`
Memory int `json:"ram_usage"`
Disk int `json:"disk_usage"`
Timestamp time.Time `json:"timestamp"`
}
// CiaoUsageHistory represents the unmarshalled version of the contents of a
// /v2.1/{tenant}/resources response. It contains snapshots of usage information
// for a given tenant over a given period of time.
type CiaoUsageHistory struct {
Usages []CiaoUsage `json:"usage"`
}
// CiaoCNCISubnet contains subnet information for a CNCI.
type CiaoCNCISubnet struct {
Subnet string `json:"subnet_cidr"`
}
// CiaoCNCI contains information about an individual CNCI.
type CiaoCNCI struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
IPv4 string `json:"IPv4"`
Geography string `json:"geography"`
Subnets []CiaoCNCISubnet `json:"subnets"`
}
// CiaoCNCIDetail represents the unmarshalled version of the contents of a
// v2.1/cncis/{cnci}/detail response. It contains information about a CNCI.
type CiaoCNCIDetail struct {
CiaoCNCI `json:"cnci"`
}
// CiaoCNCIs represents the unmarshalled version of the contents of a
// v2.1/cncis response. It contains information about all the CNCIs
// in the ciao cluster.
type CiaoCNCIs struct {
CNCIs []CiaoCNCI `json:"cncis"`
}
// NewCiaoCNCIs allocates a CiaoCNCIs structure.
// It allocates the CNCIs slice as well so that the marshalled
// JSON is an empty array and not a nil pointer, as specified by the
// OpenStack APIs.
func NewCiaoCNCIs() (cncis CiaoCNCIs) {
cncis.CNCIs = []CiaoCNCI{}
return
}
// CiaoServerStats contains status information about a CN or a NN.
type CiaoServerStats struct {
ID string `json:"id"`
NodeID string `json:"node_id"`
Timestamp time.Time `json:"updated"`
Status string `json:"status"`
TenantID string `json:"tenant_id"`
IPv4 string `json:"IPv4"`
VCPUUsage int `json:"cpus_usage"`
MemUsage int `json:"ram_usage"`
DiskUsage int `json:"disk_usage"`
}
// CiaoServersStats represents the unmarshalled version of the contents of a
// v2.1/nodes/{node}/servers/detail response. It contains general information
// about a group of instances.
type CiaoServersStats struct {
TotalServers int `json:"total_servers"`
Servers []CiaoServerStats `json:"servers"`
}
// NewCiaoServersStats allocates a CiaoServersStats structure.
// It allocates the Servers slice as well so that the marshalled
// JSON is an empty array and not a nil pointer, as specified by the
// OpenStack APIs.
func NewCiaoServersStats() (servers CiaoServersStats) {
servers.Servers = []CiaoServerStats{}
return
}
// CNCIDetail stores the IPv4 for a CNCI Agent.
type CNCIDetail struct {
IPv4 string `json:"IPv4"`
}
// CiaoServersAction represents the unmarshalled version of the contents of a
// v2.1/servers/action request. It contains an action to be performed on
// one or more instances.
type CiaoServersAction struct {
Action string `json:"action"`
ServerIDs []string `json:"servers"`
}
// CiaoTraceSummary contains information about a specific SSNTP Trace label.
type CiaoTraceSummary struct {
Label string `json:"label"`
Instances int `json:"instances"`
}
// CiaoTracesSummary represents the unmarshalled version of the response to a
// v2.1/traces request. It contains a list of all trace labels and the
// number of instances associated with them.
type CiaoTracesSummary struct {
Summaries []CiaoTraceSummary `json:"summaries"`
}
// CiaoFrameStat contains the elapsed time statistics for a frame.
type CiaoFrameStat struct {
ID string `json:"node_id"`
TotalElapsedTime float64 `json:"total_elapsed_time"`
ControllerTime float64 `json:"total_controller_time"`
LauncherTime float64 `json:"total_launcher_time"`
SchedulerTime float64 `json:"total_scheduler_time"`
}
// CiaoBatchFrameStat contains frame statisitics for a ciao cluster.
type CiaoBatchFrameStat struct {
NumInstances int `json:"num_instances"`
TotalElapsed float64 `json:"total_elapsed"`
AverageElapsed float64 `json:"average_elapsed"`
AverageControllerElapsed float64 `json:"average_controller_elapsed"`
AverageLauncherElapsed float64 `json:"average_launcher_elapsed"`
AverageSchedulerElapsed float64 `json:"average_scheduler_elapsed"`
VarianceController float64 `json:"controller_variance"`
VarianceLauncher float64 `json:"launcher_variance"`
VarianceScheduler float64 `json:"scheduler_variance"`
}
// CiaoTraceData represents the unmarshalled version of the response to a
// v2.1/traces/{label} request. It contains statistics computed from the trace
// information of SSNTP commands sent within a ciao cluster.
type CiaoTraceData struct {
Summary CiaoBatchFrameStat `json:"summary"`
FramesStat []CiaoFrameStat `json:"frames"`
}
// CiaoEvent contains information about an individual event generated
// in a ciao cluster.
type CiaoEvent struct {
Timestamp time.Time `json:"time_stamp"`
TenantID string `json:"tenant_id"`
EventType string `json:"type"`
Message string `json:"message"`
}
// CiaoEvents represents the unmarshalled version of the response to a
// v2.1/{tenant}/event or v2.1/event request.
type CiaoEvents struct {
Events []CiaoEvent `json:"events"`
}
// NewCiaoEvents allocates a CiaoEvents structure.
// It allocates the Events slice as well so that the marshalled
// JSON is an empty array and not a nil pointer, as specified by the
// OpenStack APIs.
func NewCiaoEvents() (events CiaoEvents) {
events.Events = []CiaoEvent{}
return
}
var (
// ErrQuota is returned when a resource limit is exceeded.
ErrQuota = errors.New("Over Quota")
// ErrTenantNotFound is returned when a tenant ID is unknown.
ErrTenantNotFound = errors.New("Tenant not found")
// ErrInstanceNotFound is returned when an instance is not found.
ErrInstanceNotFound = errors.New("Instance not found")
// ErrInstanceNotAssigned is returned when an instance is not assigned to a node.
ErrInstanceNotAssigned = errors.New("Cannot perform operation: instance not assigned to Node")
// ErrDuplicateSubnet is returned when a subnet already exists
ErrDuplicateSubnet = errors.New("Cannot add overlapping subnet")
// ErrDuplicateIP is returned when a duplicate external IP is added
ErrDuplicateIP = errors.New("Cannot add duplicated external IP")
// ErrInvalidIP is returned when an IP cannot be parsed
ErrInvalidIP = errors.New("The IP Address is not valid")
// ErrSubnetTooSmall is returned when an invalid subnet is used
ErrSubnetTooSmall = errors.New("Requested subnet is too small to be usable")
// ErrPoolNotFound is returned when an external IP pool is not found
ErrPoolNotFound = errors.New("Pool not found")
// ErrPoolNotEmpty is returned when a pool is still in use
ErrPoolNotEmpty = errors.New("Pool has mapped IPs")
// ErrAddressNotFound is returned when an address isn't found.
ErrAddressNotFound = errors.New("Address Not Found")
// ErrInvalidPoolAddress is returned when an address isn't part of a pool
ErrInvalidPoolAddress = errors.New("The Address is not found in this pool")
// ErrBadRequest is returned when we have a malformed request
ErrBadRequest = errors.New("Invalid Request")
// ErrPoolEmpty is returned when a pool has no free IPs
ErrPoolEmpty = errors.New("Pool has no Free IPs")
// ErrDuplicatePoolName is returned when a duplicate pool name is used
ErrDuplicatePoolName = errors.New("Pool by that name already exists")
// ErrInstanceMapped is returned when an instance cannot be deleted
// due to having an external IP assigned to it.
ErrInstanceMapped = errors.New("Unmap the external IP prior to deletion")
// ErrWorkloadNotFound is returned when a workload ID cannot be found
ErrWorkloadNotFound = errors.New("Workload not found")
// ErrWorkloadInUse is returned by DeleteWorkload when an instance of a workload is still active.
ErrWorkloadInUse = errors.New("Workload definition still in use")
// ErrBadName is returned when a name doesn't match the requirements
ErrBadName = errors.New("Requested name doesn't match requirements")
)
// Link provides a url and relationship for a resource.
type Link struct {
Rel string `json:"rel"`
Href string `json:"href"`
}
// APILink provides information and links about a supported resource.
type APILink struct {
Rel string `json:"rel"`
Href string `json:"href"`
Version string `json:"version"`
MinVersion string `json:"minimum_version"`
}
// ExternalSubnet represents a subnet for External IPs.
type ExternalSubnet struct {
ID string `json:"id"`
CIDR string `json:"subnet"`
Links []Link `json:"links"`
}
// ExternalIP represents an External IP individual address.
type ExternalIP struct {
ID string `json:"id"`
Address string `json:"address"`
Links []Link `json:"links"`
}
// Pool represents a pool of external IPs.
type Pool struct {
ID string `json:"id"`
Name string `json:"name"`
Free int `json:"free"`
TotalIPs int `json:"total_ips"`
Links []Link `json:"links"`
Subnets []ExternalSubnet `json:"subnets"`
IPs []ExternalIP `json:"ips"`
}
// NewPoolRequest is used to create a new pool.
type NewPoolRequest struct {
Name string `json:"name"`
Subnet *string `json:"subnet"`
IPs []struct {
IP string `json:"ip"`
} `json:"ips"`
}
// PoolSummary is a short form of Pool.
type PoolSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Free *int `json:"free,omitempty"`
TotalIPs *int `json:"total_ips,omitempty"`
Links []Link `json:"links,omitempty"`
}
// ListPoolsResponse respresents a summary list of all pools.
type ListPoolsResponse struct {
Pools []PoolSummary `json:"pools"`
}
// NewIPAddressRequest is used to add a new external IP to a pool.
type NewIPAddressRequest struct {
IP string `json:"ip"`
}
// NewAddressRequest is used to add a new IP or new subnet to a pool.
type NewAddressRequest struct {
Subnet *string `json:"subnet"`
IPs []NewIPAddressRequest `json:"ips"`
}
// MappedIP represents a mapping of external IP -> instance IP.
type MappedIP struct {
ID string `json:"mapping_id"`
ExternalIP string `json:"external_ip"`
InternalIP string `json:"internal_ip"`
InstanceID string `json:"instance_id"`
TenantID string `json:"tenant_id"`
PoolID string `json:"pool_id"`
PoolName string `json:"pool_name"`
Links []Link `json:"links"`
}
// MappedIPShort is a summary version of a MappedIP.
type MappedIPShort struct {
ID string `json:"mapping_id"`
ExternalIP string `json:"external_ip"`
InternalIP string `json:"internal_ip"`
InstanceID string `json:"instance_id"`
Links []Link `json:"links"`
}
// MapIPRequest is used to request that an external IP be assigned from a pool
// to a particular instance.
type MapIPRequest struct {
PoolName *string `json:"pool_name"`
InstanceID string `json:"instance_id"`
}
// QuotaDetails holds information for updating and querying quotas
type QuotaDetails struct {
Name string
Value int
Usage int
}
// MarshalJSON provides a custom marshaller for quota API
func (qd *QuotaDetails) MarshalJSON() ([]byte, error) {
var v string
if qd.Value == -1 {
v = "unlimited"
} else {
v = strconv.Itoa(qd.Value)
}
if strings.Contains(qd.Name, "limit") {
return json.Marshal(&struct {
Name string `json:"name"`
Value string `json:"value"`
}{
Name: qd.Name,
Value: v,
})
}
return json.Marshal(&struct {
Name string `json:"name"`
Value string `json:"value"`
Usage string `json:"usage"`
}{
Name: qd.Name,
Value: v,
Usage: strconv.Itoa(qd.Usage),
})
}
// UnmarshalJSON provides a custom demarshaller for quota API
func (qd *QuotaDetails) UnmarshalJSON(data []byte) error {
tmp := struct {
Name string `json:"name"`
Value string `json:"value"`
Usage string `json:"usage"`
}{}
err := json.Unmarshal(data, &tmp)
if err != nil {
return err
}
qd.Name = tmp.Name
if tmp.Value == "unlimited" {
qd.Value = -1
} else {
qd.Value, _ = strconv.Atoi(tmp.Value)
}
qd.Usage, _ = strconv.Atoi(tmp.Usage)
return nil
}
// QuotaUpdateRequest holds the layout for updating quota API
type QuotaUpdateRequest struct {
Quotas []QuotaDetails `json:"quotas"`
}
// QuotaListResponse holds the layout for returning quotas in the API
type QuotaListResponse struct {
Quotas []QuotaDetails `json:"quotas"`
}
// CNCIController is the interface for the cnci controller associated with each tenant
type CNCIController interface {
CNCIAdded(ID string) error
CNCIRemoved(ID string) error
CNCIStopped(id string) error
StartFailure(ID string) error
Active(ID string) bool
ScheduleRemoveSubnet(subnet string) error
RemoveSubnet(subnet string) error
WaitForActive(subnet string) error
GetInstanceCNCI(InstanceID string) (*Instance, error)
GetSubnetCNCI(subnet string) (*Instance, error)
Shutdown()
}
// ImageState represents the state of the image.
type ImageState string
const (
// Created means that an empty image has been created
Created ImageState = "created"
// Saving means the image is being saved
Saving ImageState = "saving"
// Active means that the image is created, uploaded and ready to use.
Active ImageState = "active"
// Killed means that an image data upload error occurred.
Killed ImageState = "killed"
)
// Visibility defines whether an image is per tenant or public.
type Visibility string
const (
// Public indicates that the image can be used by anyone.
Public Visibility = "public"
// Private indicates that the image is only available to a tenant.
Private Visibility = "private"
// Internal indicates that an image is only for Ciao internal usage.
Internal Visibility = "internal"
)
// Image contains the information that ciao will store about the image
type Image struct {
ID string `json:"id"`
State ImageState `json:"state"`
TenantID string `json:"tenant_id"`
Name string `json:"name"`
CreateTime time.Time `json:"create_time"`
Size uint64 `json:"size"`
Visibility Visibility `json:"visibility"`
}
// TransitionInstanceState safely sets thes state on an instance
func (i *Instance) TransitionInstanceState(to string) error {
i.StateLock.Lock()
defer i.StateLock.Unlock()
glog.V(2).Infof("Instance %s: %s -> %s", i.ID, i.State, to)
switch to {
case payloads.Stopping:
if i.State != payloads.Running {
return errors.New("Stop operation not allowed")
}
case payloads.Running:
if i.State != payloads.Pending {
return errors.New("Set active without pending")
}
}
i.StateChange.L.Lock()
i.State = to
i.StateChange.L.Unlock()
i.StateChange.Signal()
return nil
}