occi 2.5.19 → 3.0.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +3 -1
  3. data/AUTHORS +4 -3
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +64 -21
  6. data/README.md +19 -14
  7. data/Rakefile +12 -8
  8. data/Test Results - discovery_interface.html +862 -0
  9. data/bin/occi +333 -83
  10. data/examples/dsl_example.rb +6 -6
  11. data/examples/x509auth_example.rb +6 -6
  12. data/features/common/step_definitions/common_steps.rb +32 -0
  13. data/features/occi/core/create/create.feature +17 -0
  14. data/features/occi/core/create/step_definitions/create_steps.rb +0 -0
  15. data/features/occi/core/delete/delete.feature +14 -0
  16. data/features/occi/core/delete/step_definitions/delete_steps.rb +0 -0
  17. data/features/occi/core/discovery_interface/discovery_interface.feature +35 -0
  18. data/features/occi/core/discovery_interface/step_definitions/discovery_interface_steps.rb +19 -0
  19. data/features/occi/core/miscellaneous/miscellaneous.feature +14 -0
  20. data/features/occi/core/miscellaneous/step_definitions/miscellaneous_steps.rb +0 -0
  21. data/features/occi/core/read/read.feature +14 -0
  22. data/features/occi/core/read/step_definitions/read_steps.rb +0 -0
  23. data/features/occi/core/update/step_definitions/update_steps.rb +0 -0
  24. data/features/occi/core/update/update.feature +14 -0
  25. data/features/occi/infrastructure/create/create.feature +14 -0
  26. data/features/occi/infrastructure/create/step_definitions/create_steps.rb +0 -0
  27. data/features/support/env.rb +4 -0
  28. data/lib/occi.rb +29 -3
  29. data/lib/occi/api/client/client_amqp.rb +756 -0
  30. data/lib/occi/api/client/client_http.rb +922 -0
  31. data/lib/occi/api/client/http/httparty_fix.rb +53 -0
  32. data/lib/occi/api/client/http/net_http_fix.rb +46 -0
  33. data/lib/occi/api/dsl.rb +77 -73
  34. data/lib/occi/bin/helpers.rb +91 -0
  35. data/lib/occi/bin/occi_opts.rb +251 -0
  36. data/lib/occi/bin/resource_output_factory.rb +90 -0
  37. data/lib/occi/bin/templates/compute.erb +15 -0
  38. data/lib/occi/bin/templates/network.erb +11 -0
  39. data/lib/occi/bin/templates/os_tpl.erb +9 -0
  40. data/lib/occi/bin/templates/resource_tpl.erb +9 -0
  41. data/lib/occi/bin/templates/storage.erb +10 -0
  42. data/lib/occi/collection.rb +122 -25
  43. data/lib/occi/core.rb +18 -9
  44. data/lib/occi/core/action.rb +20 -4
  45. data/lib/occi/core/action_instance.rb +24 -0
  46. data/lib/occi/core/actions.rb +22 -0
  47. data/lib/occi/core/attribute_properties.rb +33 -84
  48. data/lib/occi/core/attributes.rb +32 -14
  49. data/lib/occi/core/categories.rb +46 -0
  50. data/lib/occi/core/category.rb +94 -20
  51. data/lib/occi/core/entities.rb +50 -0
  52. data/lib/occi/core/entity.rb +130 -89
  53. data/lib/occi/core/kind.rb +28 -35
  54. data/lib/occi/core/kinds.rb +22 -0
  55. data/lib/occi/core/link.rb +43 -40
  56. data/lib/occi/core/links.rb +34 -0
  57. data/lib/occi/core/mixin.rb +28 -23
  58. data/lib/occi/core/mixins.rb +22 -0
  59. data/lib/occi/core/related.rb +20 -0
  60. data/lib/occi/core/resource.rb +40 -40
  61. data/lib/occi/core/resources.rb +14 -0
  62. data/lib/occi/infrastructure.rb +27 -0
  63. data/lib/occi/infrastructure/compute.rb +159 -0
  64. data/lib/occi/infrastructure/network.rb +131 -0
  65. data/lib/occi/infrastructure/network/ipnetwork.rb +34 -0
  66. data/lib/occi/infrastructure/networkinterface.rb +124 -0
  67. data/lib/occi/infrastructure/networkinterface/ipnetworkinterface.rb +34 -0
  68. data/lib/occi/infrastructure/os_tpl.rb +19 -0
  69. data/lib/occi/infrastructure/resource_tpl.rb +19 -0
  70. data/lib/occi/infrastructure/storage.rb +96 -0
  71. data/lib/occi/infrastructure/storagelink.rb +73 -0
  72. data/lib/occi/log.rb +6 -2
  73. data/lib/occi/model.rb +38 -70
  74. data/lib/occi/parser.rb +108 -88
  75. data/lib/occi/version.rb +2 -2
  76. data/lib/occiantlr/OCCIANTLR.g +6 -5
  77. data/lib/occiantlr/OCCIANTLRLexer.rb +52 -52
  78. data/lib/occiantlr/OCCIANTLRParser.rb +678 -569
  79. data/lib/occiantlr/README.md +1 -1
  80. data/occi.gemspec +2 -1
  81. data/spec/cassettes/client_http_text_plain.yml +1066 -0
  82. data/spec/occi/api/client/client_amqp_spec.rb +148 -0
  83. data/spec/occi/api/client/client_http_0.5_spec.rb +292 -0
  84. data/spec/occi/api/client/client_http_spec.rb +259 -0
  85. data/spec/occi/api/dsl_spec.rb +0 -0
  86. data/spec/occi/collection_spec.rb +23 -10
  87. data/spec/occi/core/categories_spec.rb +30 -0
  88. data/spec/occi/core/category_spec.rb +41 -0
  89. data/spec/occi/core/entity_spec.rb +52 -0
  90. data/spec/occi/core/resource_spec.rb +21 -0
  91. data/spec/occi/infrastructure/compute_spec.rb +32 -0
  92. data/spec/occi/log_spec.rb +10 -10
  93. data/spec/occi/model_spec.rb +24 -24
  94. data/spec/occi/parser_spec.rb +89 -39
  95. data/spec/occi/test.json +22 -58
  96. data/spec/occiantlr/parser_spec.rb +5 -7
  97. data/spec/spec_helper.rb +13 -3
  98. metadata +116 -19
  99. data/etc/model/infrastructure/compute.json +0 -108
  100. data/etc/model/infrastructure/ipnetwork.json +0 -40
  101. data/etc/model/infrastructure/ipnetworkinterface.json +0 -40
  102. data/etc/model/infrastructure/network.json +0 -55
  103. data/etc/model/infrastructure/networkinterface.json +0 -38
  104. data/etc/model/infrastructure/os_template.json +0 -9
  105. data/etc/model/infrastructure/resource_template.json +0 -9
  106. data/etc/model/infrastructure/storage.json +0 -72
  107. data/etc/model/infrastructure/storagelink.json +0 -38
  108. data/lib/occi/api/client.rb +0 -596
  109. data/lib/occi/client/occiopts.rb +0 -146
  110. data/spec/occi/client_spec.rb +0 -12
@@ -1,40 +0,0 @@
1
- {
2
- "mixins":[
3
- {
4
- "term":"ipnetwork",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure/network#",
6
- "title":"IP Network Mixin",
7
- "attributes":{
8
- "occi":{
9
- "network":{
10
- "address":{
11
- "Mutable":true,
12
- "Required":false,
13
- "Type":"string",
14
- "Pattern":"(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*(\\/(\\d|\\d\\d|1[0-1]\\d|12[0-8]))$)|(^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(\\d|[1-2]\\d|3[0-2]))$)"
15
- },
16
- "gateway":{
17
- "Mutable":true,
18
- "Required":false,
19
- "Type":"string",
20
- "Pattern":"(^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*)"
21
- },
22
- "allocation":{
23
- "Mutable":true,
24
- "Required":false,
25
- "Type":"string",
26
- "Pattern":"dynamic|static"
27
- },
28
- "state":{
29
- "Mutable":false,
30
- "Required":false,
31
- "Type":"string",
32
- "Pattern":"active|inactive",
33
- "Default":"inactive"
34
- }
35
- }
36
- }
37
- }
38
- }
39
- ]
40
- }
@@ -1,40 +0,0 @@
1
- {
2
- "mixins":[
3
- {
4
- "term":"ipnetworkinterface",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure/networkinterface#",
6
- "title":"IP Networkinterface Mixin",
7
- "attributes":{
8
- "occi":{
9
- "networkinterface":{
10
- "address":{
11
- "Mutable":true,
12
- "Required":false,
13
- "Type":"string",
14
- "Pattern":"(^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*)"
15
- },
16
- "gateway":{
17
- "Mutable":true,
18
- "Required":false,
19
- "Type":"string",
20
- "Pattern":"(^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*)"
21
- },
22
- "allocation":{
23
- "Mutable":true,
24
- "Required":false,
25
- "Type":"string",
26
- "Pattern":"dynamic|static"
27
- },
28
- "state":{
29
- "Mutable":false,
30
- "Required":false,
31
- "Type":"string",
32
- "Pattern":"active|inactive",
33
- "Default":"inactive"
34
- }
35
- }
36
- }
37
- }
38
- }
39
- ]
40
- }
@@ -1,55 +0,0 @@
1
- {
2
- "kinds":[
3
- {
4
- "term":"network",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure#",
6
- "title":"Network Resource",
7
- "related":[
8
- "http://schemas.ogf.org/occi/core#resource"
9
- ],
10
- "attributes":{
11
- "occi":{
12
- "network":{
13
- "vlan":{
14
- "Mutable":true,
15
- "Required":false,
16
- "Type":"number",
17
- "Minimum":0,
18
- "Maximum":4095
19
- },
20
- "label":{
21
- "Mutable":true,
22
- "Required":false,
23
- "Type":"string",
24
- "Pattern":".*"
25
- },
26
- "state":{
27
- "Mutable":false,
28
- "Required":false,
29
- "Type":"string",
30
- "Pattern":"active|inactive|error",
31
- "Default":"inactive"
32
- }
33
- }
34
- }
35
- },
36
- "actions":[
37
- "http://schemas.ogf.org/occi/infrastructure/network/action#up" ,
38
- "http://schemas.ogf.org/occi/infrastructure/network/action#down"
39
- ],
40
- "location":"/network/"
41
- }
42
- ],
43
- "actions":[
44
- {
45
- "term":"up",
46
- "scheme":"http://schemas.ogf.org/occi/infrastructure/network/action#",
47
- "title":"Activate network"
48
- },
49
- {
50
- "term":"down",
51
- "scheme":"http://schemas.ogf.org/occi/infrastructure/network/action#up",
52
- "title":"Activate network"
53
- }
54
- ]
55
- }
@@ -1,38 +0,0 @@
1
- {
2
- "kinds":[
3
- {
4
- "term":"networkinterface",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure#",
6
- "title":"Networkinterface",
7
- "related":[
8
- "http://schemas.ogf.org/occi/core#link"
9
- ],
10
- "attributes":{
11
- "occi":{
12
- "networkinterface":{
13
- "interface":{
14
- "Mutable":true,
15
- "Required":false,
16
- "Type":"string",
17
- "Pattern":".*"
18
- },
19
- "mac":{
20
- "Mutable":true,
21
- "Required":false,
22
- "Type":"string",
23
- "Pattern":"^([0-9a-fA-F]{2}[:-]){5}([0-9a-fA-F]{2})$"
24
- },
25
- "state":{
26
- "Mutable":false,
27
- "Required":false,
28
- "Type":"string",
29
- "Pattern":"active|inactive",
30
- "Default":"inactive"
31
- }
32
- }
33
- }
34
- },
35
- "location":"/networkinterface/"
36
- }
37
- ]
38
- }
@@ -1,9 +0,0 @@
1
- {
2
- "mixins":[
3
- {
4
- "term":"os_tpl",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure#",
6
- "title":"Operating System Template"
7
- }
8
- ]
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "mixins":[
3
- {
4
- "term":"resource_tpl",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure#",
6
- "title":"Resource Template"
7
- }
8
- ]
9
- }
@@ -1,72 +0,0 @@
1
- {
2
- "kinds":[
3
- {
4
- "term":"storage",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure#",
6
- "title":"Storage Resource",
7
- "related":[
8
- "http://schemas.ogf.org/occi/core#resource"
9
- ],
10
- "attributes":{
11
- "occi":{
12
- "storage":{
13
- "size":{
14
- "Mutable":true,
15
- "Required":false,
16
- "Type":"number"
17
- },
18
- "state":{
19
- "Mutable":false,
20
- "Required":false,
21
- "Type":"string",
22
- "Pattern":"online|offline|backup|snapshot|resize|degraded",
23
- "Default":"offline"
24
- }
25
- }
26
- }
27
- },
28
- "actions":[
29
- "http://schemas.ogf.org/occi/infrastructure/storage/action#online",
30
- "http://schemas.ogf.org/occi/infrastructure/storage/action#offline",
31
- "http://schemas.ogf.org/occi/infrastructure/storage/action#backup",
32
- "http://schemas.ogf.org/occi/infrastructure/storage/action#snapshot",
33
- "http://schemas.ogf.org/occi/infrastructure/storage/action#resize"
34
- ],
35
- "location":"/storage/"
36
- }
37
- ],
38
- "actions":[
39
- {
40
- "term":"online",
41
- "scheme":"http://schemas.ogf.org/occi/infrastructure/storage/action#",
42
- "title":"Activate Storage"
43
- },
44
- {
45
- "term":"offline",
46
- "scheme":"http://schemas.ogf.org/occi/infrastructure/storage/action#",
47
- "title":"Deactivate Storage"
48
- },
49
- {
50
- "term":"backup",
51
- "scheme":"http://schemas.ogf.org/occi/infrastructure/storage/action#",
52
- "title":"Backup Storage"
53
- },
54
- {
55
- "term":"snapshot",
56
- "scheme":"http://schemas.ogf.org/occi/infrastructure/storage/action#",
57
- "title":"Snapshot Storage"
58
- },
59
- {
60
- "term":"resize",
61
- "scheme":"http://schemas.ogf.org/occi/infrastructure/storage/action#",
62
- "title":"Resize Storage",
63
- "attributes":{
64
- "size":{
65
- "Mutable":true,
66
- "Required":false,
67
- "Type":"number"
68
- }
69
- }
70
- }
71
- ]
72
- }
@@ -1,38 +0,0 @@
1
- {
2
- "kinds":[
3
- {
4
- "term":"storagelink",
5
- "scheme":"http://schemas.ogf.org/occi/infrastructure#",
6
- "title":"Storage Link",
7
- "related":[
8
- "http://schemas.ogf.org/occi/core#link"
9
- ],
10
- "attributes":{
11
- "occi":{
12
- "storagelink":{
13
- "deviceid":{
14
- "Mutable":true,
15
- "Required":false,
16
- "Type":"string",
17
- "Pattern":".*"
18
- },
19
- "mountpoint":{
20
- "Mutable":true,
21
- "Required":false,
22
- "Type":"string",
23
- "Pattern":".*"
24
- },
25
- "state":{
26
- "Mutable":false,
27
- "Required":false,
28
- "Type":"string",
29
- "Pattern":"active|inactive",
30
- "Default":"inactive"
31
- }
32
- }
33
- }
34
- },
35
- "location":"/storagelink/"
36
- }
37
- ]
38
- }
@@ -1,596 +0,0 @@
1
- require 'rubygems'
2
- require 'httparty'
3
-
4
- module OCCI
5
- class Client
6
-
7
- # HTTParty for raw HTTP requests
8
- include HTTParty
9
- headers 'Accept' => 'application/occi+json,text/plain;q=0.5'
10
-
11
- # a few attributes which should be visible outside the client
12
- attr_reader :endpoint
13
- attr_reader :auth_options
14
- attr_reader :media_type
15
- attr_reader :connected
16
- attr_reader :model
17
-
18
- # hash mapping human-readable resource names to OCCI identifiers
19
- # TODO: get resources dynamically from the model
20
- RESOURCES = {
21
- :compute => "http://schemas.ogf.org/occi/infrastructure#compute",
22
- :storage => "http://schemas.ogf.org/occi/infrastructure#storage",
23
- :network => "http://schemas.ogf.org/occi/infrastructure#network"
24
- }
25
-
26
- # hash mapping HTTP response codes to human-readable messages
27
- HTTP_CODES = {
28
- "100" => "Continue",
29
- "101" => "Switching Protocols",
30
- "200" => "OK",
31
- "201" => "Created",
32
- "202" => "Accepted",
33
- "203" => "Non-Authoritative Information",
34
- "204" => "No Content",
35
- "205" => "Reset Content",
36
- "206" => "Partial Content",
37
- "300" => "Multiple Choices",
38
- "301" => "Moved Permanently",
39
- "302" => "Found",
40
- "303" => "See Other",
41
- "304" => "Not Modified",
42
- "305" => "Use Proxy",
43
- "307" => "Temporary Redirect",
44
- "400" => "Bad Request",
45
- "401" => "Unauthorized",
46
- "402" => "Payment Required",
47
- "403" => "Forbidden",
48
- "404" => "Not Found",
49
- "405" => "Method Not Allowed",
50
- "406" => "Not Acceptable",
51
- "407" => "Proxy Authentication Required",
52
- "408" => "Request Time-out",
53
- "409" => "Conflict",
54
- "410" => "Gone",
55
- "411" => "Length Required",
56
- "412" => "Precondition Failed",
57
- "413" => "Request Entity Too Large",
58
- "414" => "Request-URI Too Large",
59
- "415" => "Unsupported Media Type",
60
- "416" => "Requested range not satisfiable",
61
- "417" => "Expectation Failed",
62
- "500" => "Internal Server Error",
63
- "501" => "Not Implemented",
64
- "502" => "Bad Gateway",
65
- "503" => "Service Unavailable",
66
- "504" => "Gateway Time-out",
67
- "505" => "HTTP Version not supported"
68
- }
69
-
70
- # @param [String] Endpoint URI
71
- # @param [Hash] Auth options
72
- # @param [Hash] Logging options
73
- # @param [Boolean] Enable autoconnect?
74
- # @return [OCCI:Client] Client instance
75
- def initialize(endpoint = "http://localhost:3000/", auth_options = {:type => "none"}, log_options = { :out => STDERR, :level => OCCI::Log::WARN, :logger => nil}, auto_connect = true, media_type = nil)
76
- # set OCCI::Log
77
- set_logger log_options
78
-
79
- # pass auth options to HTTParty
80
- change_auth auth_options
81
-
82
- # check the validity and canonize the endpoint URI
83
- prepare_endpoint endpoint
84
-
85
- # get accepted media types from HTTParty
86
- set_media_type
87
-
88
- # force media_type if provided
89
- if media_type
90
- self.class.headers 'Accept' => media_type
91
- @media_type = media_type
92
- end
93
-
94
- OCCI::Log.debug("Media Type: #{@media_type}")
95
- OCCI::Log.debug("Headers: #{self.class.headers}")
96
-
97
- # get model information from the endpoint
98
- # and create OCCI::Model instance
99
- set_model
100
-
101
- # auto-connect?
102
- @connected = auto_connect
103
- end
104
-
105
- # @param [String] Resource name or resource identifier
106
- # @return [OCCI::Core::Entity] Resource instance
107
- def get_resource(resource_type)
108
-
109
- OCCI::Log.debug("Instantiating #{resource_type} ...")
110
-
111
- if RESOURCES.has_value? resource_type
112
- # we got a resource type identifier
113
- OCCI::Core::Resource.new resource_type
114
- elsif RESOURCES.has_key? resource_type.to_sym
115
- # we got a resource type name
116
- OCCI::Core::Resource.new get_resource_type_identifier(resource_type)
117
- else
118
- raise "Unknown resource type! [#{resource_type}]"
119
- end
120
-
121
- end
122
-
123
- # @return [Array] List of available resource types in a human-readable format
124
- def get_resource_types
125
- OCCI::Log.debug("Getting resource types ...")
126
- RESOURCES.keys.map! { |k| k.to_s }
127
- end
128
-
129
- # @return [Array] List of available resource types in a OCCI ID format
130
- def get_resource_type_identifiers
131
- OCCI::Log.debug("Getting resource identifiers ...")
132
- RESOURCES.values
133
- end
134
-
135
- # @param [String] Name of the mixin
136
- # @param [String] Type of the mixin
137
- # @param [Boolean] Should we describe the mixin or return its link?
138
- # @return [String, OCCI:Collection] Link or mixin description
139
- def find_mixin(name, type = nil, describe = false)
140
-
141
- OCCI::Log.debug("Looking for mixin #{name} + #{type} + #{describe}")
142
-
143
- # is type valid?
144
- unless type.nil?
145
- raise "Unknown mixin type! [#{type}]" unless @mixins.has_key? type.to_sym
146
- end
147
-
148
- # TODO: extend this code to support multiple matches and regex filters
149
- # should we look for links or descriptions?
150
- unless describe
151
- # we are looking for links
152
- # prefix mixin name with '#' to simplify the search
153
- name = "#" + name
154
- unless type
155
- # there is no type preference, return first global match
156
- @mixins.flatten(2).select { |mixin| mixin.to_s.reverse.start_with? name.reverse }.first
157
- else
158
- # return the first match with the selected type
159
- @mixins[type.to_sym].select { |mixin| mixin.to_s.reverse.start_with? name.reverse }.first
160
- end
161
- else
162
- # we are looking for descriptions
163
- unless type
164
- # try in os_tpls first
165
- found = get_os_templates.select { |mixin| mixin.term == name }.first
166
-
167
- # then try in resource_tpls
168
- unless found
169
- found = get_resource_templates.select { |template| template.term == name }.first
170
- end
171
-
172
- found
173
- else
174
- # get the first match from either os_tpls or resource_tpls
175
- case
176
- when type == "os_tpl"
177
- get_os_templates.select { |mixin| mixin.term == name }.first
178
- when type == "resource_tpl"
179
- get_resource_templates.select { |template| template.term == name }.first
180
- else
181
- nil
182
- end
183
- end
184
- end
185
- end
186
-
187
- # @param [String] Type of mixins to return
188
- # @return [Array] List of available mixins
189
- def get_mixins(type = nil)
190
- unless type.nil?
191
- # is type valid?
192
- raise "Unknown mixin type! #{type}" unless @mixins.has_key? type.to_sym
193
-
194
- # return mixin of the selected type
195
- @mixins[type.to_sym]
196
- else
197
- # we did not get a type, return all mixins
198
- mixins = []
199
-
200
- # flatten the hash and remove its keys
201
- get_mixin_types.each do |type|
202
- mixins.concat @mixins[type.to_sym]
203
- end
204
-
205
- mixins
206
- end
207
- end
208
-
209
- # @return [Array] List of available mixin types
210
- def get_mixin_types
211
- @mixins.keys.map! { |k| k.to_s }
212
- end
213
-
214
- # @return [Array] List of available mixin type identifiers
215
- def get_mixin_type_identifiers
216
- identifiers = []
217
-
218
- get_mixin_types.each do |mixin_type|
219
- identifiers << 'http://schemas.ogf.org/occi/infrastructure#' + mixin_type
220
- end
221
-
222
- identifiers
223
- end
224
-
225
- # @param [String] Human-readable name of the resource
226
- # @return [String] OCCI resource identifier
227
- def get_resource_type_identifier(resource_type)
228
- raise "Unknown resource type! [#{resource_type}]" unless RESOURCES.has_key? resource_type.to_sym
229
-
230
- RESOURCES[resource_type.to_sym]
231
- end
232
-
233
- # @param [String] OCCI resource identifier
234
- # @return [String] Human-readable name of the resource
235
- def get_resource_type(resource_type_identifier)
236
- raise "Unknown resource type identifier! [#{resource_type_identifier}]" unless RESOURCES.has_value? resource_type_identifier
237
-
238
- RESOURCES.key(resource_type_identifier).to_s
239
- end
240
-
241
- # @param [String] OCCI resource type identifier or just type
242
- # @return [Array] List of links
243
- def list(resource_type_identifier)
244
-
245
- # convert type to type identifier
246
- unless resource_type_identifier.start_with? "http://" or resource_type_identifier.start_with? "https://"
247
- resource_type_identifier = get_resource_type_identifier resource_type_identifier
248
- end
249
-
250
- # check some basic pre-conditions
251
- raise "Endpoint is not connected!" unless @connected
252
- raise "Unkown resource type identifier! [#{resource_type_identifier}]" unless RESOURCES.has_value? resource_type_identifier
253
-
254
- # split the type identifier and get the most important part
255
- uri_part = resource_type_identifier.split('#').last
256
-
257
- list = []
258
-
259
- # request uri-list from the server
260
- path = uri_part + '/'
261
- list = self.class.get(@endpoint + path, :headers => { "Accept" => 'text/uri-list' }).body.split("\n").compact
262
-
263
- list
264
- end
265
-
266
- # @param [String] OCCI resource type identifier or just type
267
- # @return [OCCI::Collection] List of descriptions
268
- def describe(resource_identifier)
269
-
270
- # convert type to type identifier
271
- unless resource_identifier.start_with? "http://" or resource_identifier.start_with? "https://"
272
- resource_identifier = get_resource_type_identifier resource_identifier
273
- end
274
-
275
- # check some basic pre-conditions
276
- raise "Endpoint is not connected!" unless @connected
277
-
278
- descriptions = nil
279
-
280
- if RESOURCES.has_value? resource_identifier
281
- # we got type identifier
282
- # split the type identifier
283
- uri_part = resource_identifier.split('#').last
284
- # make the request
285
- descriptions = get(uri_part + '/')
286
- elsif resource_identifier.start_with? @endpoint
287
- # we got resource link
288
- # make the request
289
- descriptions = get(sanitize_resource_link(resource_identifier))
290
- else
291
- raise "Unkown resource identifier! [#{resource_identifier}]"
292
- end
293
-
294
- descriptions
295
- end
296
-
297
- # @param [OCCI::Core::Entity] Entity to be created on the server
298
- # @return [String] Link (URI) or the new resource
299
- def create(entity)
300
-
301
- # check some basic pre-conditions
302
- raise "Endpoint is not connected!" unless @connected
303
- raise "#{entity} not an entity" unless entity.kind_of? OCCI::Core::Entity
304
-
305
- # is this entity valid?
306
- entity.check(@model)
307
- kind = @model.get_by_id(entity.kind)
308
- raise "No kind found for #{entity}" unless kind
309
-
310
- # get location for this kind of entity
311
- location = @model.get_by_id(entity.kind).location
312
- collection = OCCI::Collection.new
313
-
314
- # is this entity a Resource or a Link?
315
- collection.resources << entity if entity.kind_of? OCCI::Core::Resource
316
- collection.links << entity if entity.kind_of? OCCI::Core::Link
317
-
318
- # make the request
319
- post location, collection
320
- end
321
-
322
- # @param [String] Resource link (URI)
323
- # @return [Boolean] Success?
324
- def delete(resource_identifier)
325
- # TODO: delete should work for entire resource types
326
- # check some basic pre-conditions
327
- raise "Endpoint is not connected!" unless @connected
328
- raise "Unknown resource identifier! #{resource_identifier}" unless resource_identifier.start_with? @endpoint
329
-
330
- # make the request
331
- del(sanitize_resource_link(resource_identifier))
332
- end
333
-
334
- # @param [String] Resource link (URI)
335
- # @param [String] Type of action
336
- # @return [String] Resource link (URI)
337
- def trigger(resource_identifier, action)
338
- # TODO: not tested
339
- # check some basic pre-conditions
340
- raise "Endpoint is not connected!" unless @connected
341
- raise "Unknown resource identifier! #{resource_identifier}" unless resource_identifier.start_with? @endpoint
342
-
343
- # encapsulate the acion in a collection
344
- collection = OCCI::Collection.new
345
- collection.actions << action
346
-
347
- # make the request
348
- post sanitize_resource_link(resource_identifier), collection
349
- end
350
-
351
- def refresh
352
- # re-download the model from the server
353
- set_model
354
- end
355
-
356
- # @param [OCCI::Core::Resource] Compute instance
357
- # @param [URI,String] Storage location (URI)
358
- # @param [OCCI::Core::Attributes] Attributes
359
- # @param [Array] Mixins
360
- # @return [OCCI::Core::Link] Link instance
361
- def storagelink(compute, storage_location, attributes=OCCI::Core::Attributes.new, mixins=[])
362
- kind = 'http://schemas.ogf.org/occi/infrastructure#storagelink'
363
- storage_kind = 'http://schemas.ogf.org/occi/infrastructure#storage'
364
- storagelink = link(kind, compute, storage_location, storage_kind, attributes, mixins)
365
-
366
- storagelink
367
- end
368
-
369
- # @param [OCCI::Core::Resource] Compute instance
370
- # @param [URI,String] Network location (URI)
371
- # @param [OCCI::Core::Attributes] Attributes
372
- # @param [Array] Mixins
373
- # @return [OCCI::Core::Link] Link instance
374
- def networkinterface(compute, network_location, attributes=OCCI::Core::Attributes.new, mixins=[])
375
- kind = 'http://schemas.ogf.org/occi/infrastructure#networkinterface'
376
- network_kind = 'http://schemas.ogf.org/occi/infrastructure#network'
377
- networkinterface = link(kind, compute, network_location, network_kind, attributes, mixins)
378
-
379
- networkinterface
380
- end
381
-
382
- #private
383
-
384
- # @param [Hash]
385
- def set_logger(log_options)
386
-
387
- if log_options[:logger].nil? or not (log_options[:logger].kind_of? OCCI::Log)
388
- logger = OCCI::Log.new(log_options[:out])
389
- logger.level = log_options[:level]
390
- end
391
-
392
- self.class.debug_output $stderr if log_options[:level] == OCCI::Log::DEBUG
393
-
394
- end
395
-
396
- # @param [Hash]
397
- def change_auth(auth_options)
398
- @auth_options = auth_options
399
-
400
- case @auth_options[:type]
401
- when "basic"
402
- # set up basic auth
403
- raise ArgumentError, "Missing required options 'username' and 'password' for basic auth!" unless @auth_options[:username] and @auth_options[:password]
404
- self.class.basic_auth @auth_options[:username], @auth_options[:password]
405
- when "digest"
406
- # set up digest auth
407
- raise ArgumentError, "Missing required options 'username' and 'password' for digest auth!" unless @auth_options[:username] and @auth_options[:password]
408
- self.class.digest_auth @auth_options[:username], @auth_options[:password]
409
- when "x509"
410
- # set up pem and optionally pem_password and ssl_ca_path
411
- raise ArgumentError, "Missing required option 'user_cert' for x509 auth!" unless @auth_options[:user_cert]
412
- raise ArgumentError, "The file specified in 'user_cert' does not exist!" unless File.exists? @auth_options[:user_cert]
413
-
414
- self.class.pem File.read(@auth_options[:user_cert]), @auth_options[:user_cert_password]
415
- self.class.ssl_ca_path @auth_options[:ca_path] unless @auth_options[:ca_path].nil? or @auth_options[:ca_path].empty?
416
- when "none", nil
417
- # do nothing
418
- else
419
- raise ArgumentError, "Unknown AUTH method [#{@auth_options[:type]}]!"
420
- end
421
- end
422
-
423
- # @param [String]
424
- # @param [OCCI::Collection]
425
- # @return [OCCI::Collection]
426
- def get(path='', filter=nil)
427
- path = path.reverse.chomp('/').reverse
428
- response = if filter
429
- categories = filter.categories.collect { |category| category.to_text }.join(',')
430
- attributes = filter.entities.collect { |entity| entity.attributes.combine.collect { |k, v| k + '=' + v } }.join(',')
431
-
432
- headers = self.class.headers.clone
433
- headers['Content-Type'] = 'text/occi'
434
- headers['Category'] = categories unless categories.empty?
435
- headers['X-OCCI-Attributes'] = attributes unless attributes.empty?
436
-
437
- self.class.get(@endpoint + path, :headers => headers)
438
- else
439
- self.class.get(@endpoint + path)
440
- end
441
-
442
- response_msg = response_message response
443
- raise "HTTP GET failed! #{response_msg}" unless response.code.between? 200, 300
444
-
445
- kind = @model.get_by_location path if @model
446
- kind ? entity_type = kind.entity_type : entity_type = nil
447
- _, collection = OCCI::Parser.parse(response.content_type, response.body, path.include?('-/'), entity_type)
448
-
449
- collection
450
- end
451
-
452
- # @param [String]
453
- # @param [OCCI::Collection]
454
- # @return [String]
455
- def post(path, collection)
456
- path = path.reverse.chomp('/').reverse
457
- response = if @media_type == 'application/occi+json'
458
- self.class.post(@endpoint + path,
459
- :body => collection.to_json,
460
- :headers => { 'Accept' => 'text/uri-list', 'Content-Type' => 'application/occi+json' })
461
- else
462
- self.class.post(@endpoint + path,
463
- :body => collection.to_text,
464
- :headers => { 'Accept' => 'text/uri-list', 'Content-Type' => 'text/plain' })
465
- end
466
-
467
- response_msg = response_message response
468
- raise "HTTP POST failed! #{response_msg}" unless response.code.between? 200, 300
469
-
470
- URI.parse(response.body).to_s
471
- end
472
-
473
- # @param [String]
474
- # @param [OCCI::Collection]
475
- # @return [OCCI::Collection]
476
- def put(path, collection)
477
- path = path.reverse.chomp('/').reverse
478
- response = if @media_type == 'application/occi+json'
479
- self.class.post(@endpoint + path, :body => collection.to_json, :headers => { 'Content-Type' => 'application/occi+json' })
480
- else
481
- self.class.post(@endpoint + path, { :body => collection.to_text, :headers => { 'Content-Type' => 'text/plain' } })
482
- end
483
-
484
- response_msg = response_message response
485
- raise "HTTP PUT failed! #{response_msg}" unless response.code.between? 200, 300
486
-
487
- _, collection = OCCI::Parser.parse(response.content_type, response.body)
488
-
489
- collection
490
- end
491
-
492
- # @param [String]
493
- # @param [OCCI::Collection]
494
- # @return [Boolean]
495
- def del(path, collection=nil)
496
- path = path.reverse.chomp('/').reverse
497
- response = self.class.delete(@endpoint + path)
498
-
499
- response_msg = response_message response
500
- raise "HTTP DELETE failed! #{response_msg}" unless response.code.between? 200, 300
501
-
502
- true
503
- end
504
-
505
- # @param [String]
506
- # @param [OCCI::Core::Resource]
507
- # @param [URI,String]
508
- # @param [String]
509
- # @param [OCCI::Core::Attributes]
510
- # @param [Array]
511
- # @return [OCCI::Core::Link]
512
- def link(kind, source, target_location, target_kind, attributes=OCCI::Core::Attributes.new, mixins=[])
513
- link = OCCI::Core::Link.new(kind)
514
- link.mixins = mixins
515
- link.attributes = attributes
516
- link.target = (target_location.kind_of? URI::Generic) ? target_location.path : target_location.to_s
517
- link.rel = target_kind
518
-
519
- jj link
520
- link.check @model
521
- source.links << link
522
- link
523
- end
524
-
525
- # @param [String]
526
- # @return [String]
527
- def prepare_endpoint(endpoint)
528
- raise 'Endpoint not a valid URI' if (endpoint =~ URI::ABS_URI).nil?
529
- @endpoint = endpoint.chomp('/') + '/'
530
- end
531
-
532
- # @param [String]
533
- # @return [String]
534
- def sanitize_resource_link(resource_link)
535
- raise "Resource link #{resource_link} is not valid!" unless resource_link.start_with? @endpoint
536
-
537
- resource_link.gsub @endpoint, '/'
538
- end
539
-
540
- def set_model
541
-
542
- #
543
- model = get('/-/')
544
- @model = OCCI::Model.new(model)
545
-
546
- @mixins = {
547
- :os_tpl => [],
548
- :resource_tpl => []
549
- }
550
-
551
- #
552
- get_os_templates.each do |os_tpl|
553
- @mixins[:os_tpl] << os_tpl.type_identifier unless os_tpl.nil? or os_tpl.type_identifier.nil?
554
- end
555
-
556
- #
557
- get_resource_templates.each do |res_tpl|
558
- @mixins[:resource_tpl] << res_tpl.type_identifier unless res_tpl.nil? or res_tpl.type_identifier.nil?
559
- end
560
- end
561
-
562
- # @return [OCCI::Collection] collection including all registered OS templates
563
- def get_os_templates
564
- @model.get.mixins.select { |mixin| mixin.related.select { |rel| rel.end_with? 'os_tpl' }.any? }
565
- end
566
-
567
- # @return [OCCI::Collection] collection including all registered resource templates
568
- def get_resource_templates
569
- @model.get.mixins.select { |mixin| mixin.related.select { |rel| rel.end_with? 'resource_tpl' }.any? }
570
- end
571
-
572
- # @return [String]
573
- def set_media_type
574
- media_types = self.class.head(@endpoint).headers['accept']
575
- OCCI::Log.debug("Available media types: #{media_types}")
576
- @media_type = case media_types
577
- when /application\/occi\+json/
578
- 'application/occi+json'
579
- else
580
- 'text/plain'
581
- end
582
- end
583
-
584
- # @param [HTTParty::Response]
585
- def response_message(response)
586
- 'HTTP Response status: [' + response.code.to_s + '] ' + reason_phrase(response.code)
587
- end
588
-
589
- # @param [Integer]
590
- # @return [String]
591
- def reason_phrase(code)
592
- HTTP_CODES[code.to_s]
593
- end
594
-
595
- end
596
- end