Class: OpenNebula::Service
- Inherits:
-
DocumentJSON
- Object
- XMLElement
- PoolElement
- Document
- DocumentJSON
- OpenNebula::Service
- Defined in:
- lib/models/service.rb
Overview
Service class as wrapper of DocumentJSON
Constant Summary collapse
- DOCUMENT_TYPE =
100
- STATE =
{ 'PENDING' => 0, 'DEPLOYING' => 1, 'RUNNING' => 2, 'UNDEPLOYING' => 3, 'WARNING' => 4, 'DONE' => 5, 'FAILED_UNDEPLOYING' => 6, 'FAILED_DEPLOYING' => 7, 'SCALING' => 8, 'FAILED_SCALING' => 9, 'COOLDOWN' => 10, 'DEPLOYING_NETS' => 11, 'UNDEPLOYING_NETS' => 12, 'FAILED_DEPLOYING_NETS' => 13, 'FAILED_UNDEPLOYING_NETS' => 14, 'HOLD' => 15 }
- STATE_STR =
[ 'PENDING', 'DEPLOYING', 'RUNNING', 'UNDEPLOYING', 'WARNING', 'DONE', 'FAILED_UNDEPLOYING', 'FAILED_DEPLOYING', 'SCALING', 'FAILED_SCALING', 'COOLDOWN', 'DEPLOYING_NETS', 'UNDEPLOYING_NETS', 'FAILED_DEPLOYING_NETS', 'FAILED_UNDEPLOYING_NETS', 'HOLD' ]
- TRANSIENT_STATES =
[ 'DEPLOYING', 'UNDEPLOYING', 'SCALING', 'COOLDOWN', 'DEPLOYING_NETS', 'UNDEPLOYING_NETS' ]
- FAILED_STATES =
[ 'FAILED_DEPLOYING', 'FAILED_UNDEPLOYING', 'FAILED_SCALING', 'FAILED_DEPLOYING_NETS', 'FAILED_UNDEPLOYING_NETS' ]
- RECOVER_DEPLOY_STATES =
[ 'FAILED_DEPLOYING', 'DEPLOYING', 'PENDING' ]
- RECOVER_UNDEPLOY_STATES =
[ 'FAILED_UNDEPLOYING', 'UNDEPLOYING', 'FAILED_UNDEPLOYING_NETS' ]
- RECOVER_SCALE_STATES =
[ 'FAILED_SCALING', 'SCALING' ]
- RECOVER_DEPLOY_NETS_STATES =
['DEPLOYING_NETS', 'FAILED_DEPLOYING_NETS']
- RECOVER_UNDEPLOY_NETS_STATES =
[ 'UNDEPLOYING_NETS', 'FAILED_UNDEPLOYING_NETS' ]
- IMMUTABLE_ATTRS =
List of attributes that can’t be changed in update operation
custom_attrs: it only has sense when deploying, not in running custom_attrs_values: it only has sense when deploying, not in running deployment: changing this, changes the undeploy operation log: this is just internal information, no sense to change it name: this has to be changed using rename operation networks: it only has sense when deploying, not in running networks_values: it only has sense when deploying, not in running ready_status_gate: it only has sense when deploying, not in running state: this is internal information managed by OneFlow server start_time: this is internal information managed by OneFlow server
[ 'custom_attrs', 'custom_attrs_values', 'deployment', 'log', 'name', 'networks', 'networks_values', 'ready_status_gate', 'state', 'start_time' ]
- LOG_COMP =
'SER'
Constants inherited from DocumentJSON
Constants inherited from Document
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#roles ⇒ Object
readonly
Returns the value of attribute roles.
Attributes inherited from PoolElement
Instance Method Summary collapse
-
#add_role(template) ⇒ OpenNebula::Role
Adds a role to the service.
-
#all_roles_done? ⇒ true, false
Returns true if all the nodes are in done state.
-
#all_roles_hold? ⇒ true, false
Returns true if all the nodes are in hold state.
-
#all_roles_running? ⇒ true, false
Returns true if all the nodes are correctly deployed.
-
#allocate(template_json) ⇒ nil, OpenNebula::Error
Create a new service based on the template provided.
- #can_recover_deploy? ⇒ Boolean
- #can_recover_deploy_nets? ⇒ Boolean
- #can_recover_scale? ⇒ Boolean
- #can_recover_undeploy? ⇒ Boolean
- #can_recover_undeploy_nets? ⇒ Boolean
- #can_scale? ⇒ Boolean
-
#can_undeploy? ⇒ Boolean
Return true if the service can be undeployed.
-
#can_update? ⇒ Boolean
Return true if the service can be updated.
-
#check_new_template(template_json, append) ⇒ Boolean, String
Check that changes values are correct.
-
#check_role(role) ⇒ Boolean
Check if role is terminated or not.
-
#chown(uid, gid) ⇒ nil, OpenNebula::Error
Changes the owner/group.
- #delete_networks ⇒ Object
- #deploy_networks(deploy = true) ⇒ Object
-
#failed_state? ⇒ Boolean
Return true if the service is in failed state.
- #gid ⇒ Object
- #hold? ⇒ Boolean
-
#info ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
-
#info_roles ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
-
#log_error(message) ⇒ Object
Add an error message in the service information that will be stored in OpenNebula.
-
#log_info(message) ⇒ Object
Add an info message in the service information that will be stored in OpenNebula.
-
#networks(deploy) ⇒ Array
Returns virtual networks IDs.
-
#on_hold? ⇒ true, false
Returns the on_hold service option.
-
#recover ⇒ nil, OpenNebula::Error
Recover a failed service.
-
#remove_role(name) ⇒ Object
Removes a role from the service.
-
#replace_client(owner_client) ⇒ Object
Replaces this object’s client with a new one.
-
#report_ready? ⇒ true, false
Returns the running_status_vm option.
-
#running? ⇒ Boolean
Return true if the service is running.
-
#set_state(state) ⇒ true, false
Sets a new state rubocop:disable Naming/AccessorMethodName.
- #shutdown_action ⇒ Object
-
#state ⇒ Integer
Returns the service state.
-
#state_str ⇒ Object
Returns the string representation of the service state.
-
#strategy ⇒ String
Returns the service strategy.
-
#transient_state? ⇒ Boolean
Returns true if the service is in transient state.
- #uname ⇒ Object
-
#update(template_json = nil, append = false) ⇒ nil, OpenNebula::Error
Replaces the template contents.
-
#update_raw(template_raw, append = false) ⇒ nil, OpenNebula::Error
Replaces the raw template contents.
-
#update_role(role_name, template_json) ⇒ nil, OpenNebula::Error
Updates a role.
Methods inherited from DocumentJSON
#allocate_xml, #build_template_xml, #load_body, #template_tag, #to_json
Methods inherited from Document
build_xml, #chmod, #chmod_octet, #clone, #delete, #document_type, #initialize, #owner_id, #public?, #rename
Methods inherited from PoolElement
#id, new_with_id, #replace, #to_str
Methods inherited from XMLElement
#[], #add_element, #attr, build_xml, #delete_element, #each, #each_xpath, #element_xml, #has_elements?, #initialize, #initialize_xml, #name, #retrieve_elements, #retrieve_xmlelements, #set_content, #template_like_str, #template_str, #template_xml, #text, #to_hash, #to_xml, #xml_nil?
Constructor Details
This class inherits a constructor from OpenNebula::Document
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
22 23 24 |
# File 'lib/models/service.rb', line 22 def client @client end |
#roles ⇒ Object (readonly)
Returns the value of attribute roles.
22 23 24 |
# File 'lib/models/service.rb', line 22 def roles @roles end |
Instance Method Details
#add_role(template) ⇒ OpenNebula::Role
Adds a role to the service
412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/models/service.rb', line 412 def add_role(template) template['state'] ||= Role::STATE['PENDING'] role = Role.new(template, self) if @roles[role.name] return OpenNebula::Error.new("Role #{role.name} already exists") end @roles[role.name] = role @body['roles'] << template if @body && @body['roles'] role end |
#all_roles_done? ⇒ true, false
Returns true if all the nodes are in done state
270 271 272 273 274 275 276 277 278 |
# File 'lib/models/service.rb', line 270 def all_roles_done? @roles.each do |_name, role| if role.state != Role::STATE['DONE'] return false end end true end |
#all_roles_hold? ⇒ true, false
Returns true if all the nodes are in hold state
282 283 284 285 286 287 288 289 290 |
# File 'lib/models/service.rb', line 282 def all_roles_hold? @roles.each do |_name, role| if role.state != Role::STATE['HOLD'] return false end end true end |
#all_roles_running? ⇒ true, false
Returns true if all the nodes are correctly deployed
258 259 260 261 262 263 264 265 266 |
# File 'lib/models/service.rb', line 258 def all_roles_running? @roles.each do |_name, role| if role.state != Role::STATE['RUNNING'] return false end end true end |
#allocate(template_json) ⇒ nil, OpenNebula::Error
Create a new service based on the template provided
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/models/service.rb', line 314 def allocate(template_json) template = JSON.parse(template_json) template['state'] = STATE['PENDING'] if template['roles'] template['roles'].each do |elem| elem['state'] ||= Role::STATE['PENDING'] end end template['start_time'] = Integer(Time.now) # Replace $attibute by the corresponding value resolve_attributes(template) super(template.to_json, template['name']) end |
#can_recover_deploy? ⇒ Boolean
181 182 183 |
# File 'lib/models/service.rb', line 181 def can_recover_deploy? RECOVER_DEPLOY_STATES.include? STATE_STR[state] end |
#can_recover_deploy_nets? ⇒ Boolean
193 194 195 |
# File 'lib/models/service.rb', line 193 def can_recover_deploy_nets? RECOVER_DEPLOY_NETS_STATES.include?(STATE_STR[state]) end |
#can_recover_scale? ⇒ Boolean
189 190 191 |
# File 'lib/models/service.rb', line 189 def can_recover_scale? RECOVER_SCALE_STATES.include? STATE_STR[state] end |
#can_recover_undeploy? ⇒ Boolean
185 186 187 |
# File 'lib/models/service.rb', line 185 def can_recover_undeploy? RECOVER_UNDEPLOY_STATES.include? STATE_STR[state] end |
#can_recover_undeploy_nets? ⇒ Boolean
197 198 199 |
# File 'lib/models/service.rb', line 197 def can_recover_undeploy_nets? RECOVER_UNDEPLOY_NETS_STATES.include?(STATE_STR[state]) end |
#can_scale? ⇒ Boolean
692 693 694 |
# File 'lib/models/service.rb', line 692 def can_scale? state == Service::STATE['RUNNING'] end |
#can_undeploy? ⇒ Boolean
Return true if the service can be undeployed
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/models/service.rb', line 164 def can_undeploy? # rubocop:disable Style/IfWithBooleanLiteralBranches if (transient_state? && state != Service::STATE['UNDEPLOYING']) || state == Service::STATE['DONE'] || failed_state? false else true end # rubocop:enable Style/IfWithBooleanLiteralBranches end |
#can_update? ⇒ Boolean
Return true if the service can be updated
177 178 179 |
# File 'lib/models/service.rb', line 177 def can_update? !transient_state? && !failed_state? end |
#check_new_template(template_json, append) ⇒ Boolean, String
Check that changes values are correct
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 |
# File 'lib/models/service.rb', line 603 def check_new_template(template_json, append) template = JSON.parse(template_json) if append IMMUTABLE_ATTRS.each do |attr| next if template[attr].nil? return [false, "service/#{attr}"] end else if template['roles'].size != @roles.size return [false, 'service/roles size'] end IMMUTABLE_ATTRS.each do |attr| next if template[attr] == @body[attr] return [false, "service/#{attr}"] end template['roles'].each do |role| # Role name can't be changed, if it is changed some problems # may appear, as name is used to reference roles return [false, 'name'] unless @roles[role['name']] rc = @roles[role['name']].check_new_template(role) return rc unless rc[0] end end [true, nil] end |
#check_role(role) ⇒ Boolean
Check if role is terminated or not
703 704 705 706 707 708 709 710 711 712 713 |
# File 'lib/models/service.rb', line 703 def check_role(role) return unless @body['automatic_deletion'] return unless role.nodes.empty? ret = true @body['roles'].each {|r| ret &= r['nodes'].empty? } ret end |
#chown(uid, gid) ⇒ nil, OpenNebula::Error
Changes the owner/group
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 |
# File 'lib/models/service.rb', line 476 def chown(uid, gid) old_uid = self['UID'].to_i old_gid = self['GID'].to_i rc = super(uid, gid) if OpenNebula.is_error?(rc) return rc end @roles.each do |_name, role| rc = role.chown(uid, gid) break if rc[0] == false end if rc[0] == false log_error('Chown operation failed, will try to rollback ' \ 'all VMs to the old user and group') update super(old_uid, old_gid) @roles.each do |_name, role| role.chown(old_uid, old_gid) end return OpenNebula::Error.new(rc[1]) end nil end |
#delete_networks ⇒ Object
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 |
# File 'lib/models/service.rb', line 670 def delete_networks vnets = @body['networks_values'] vnets_failed = [] return if vnets.nil? vnets.each do |vnet| vnet.each do |_, net| next unless net.key?('template_id') || net.key?('reserve_from') rc = OpenNebula::VirtualNetwork.new_with_id( net['id'], @client ).delete vnets_failed << net['id'] if OpenNebula.is_error?(rc) end end vnets_failed end |
#deploy_networks(deploy = true) ⇒ Object
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 |
# File 'lib/models/service.rb', line 637 def deploy_networks(deploy = true) body = if deploy JSON.parse(self['TEMPLATE/BODY']) else @body end return if body['networks_values'].nil? body['networks_values'].each do |vnet| vnet.each do |name, net| next if net.key?('id') if net.key?('template_id') rc = create_vnet(name, net) elsif net.key?('reserve_from') rc = reserve(name, net) end return rc if OpenNebula.is_error?(rc) net['id'] = rc end end if deploy # Replace $attibute by the corresponding value resolve_networks(body) # @body = template.to_hash update_body(body) end |
#failed_state? ⇒ Boolean
Return true if the service is in failed state
158 159 160 |
# File 'lib/models/service.rb', line 158 def failed_state? FAILED_STATES.include? STATE_STR[state] end |
#gid ⇒ Object
217 218 219 |
# File 'lib/models/service.rb', line 217 def gid self['GID'].to_i end |
#hold? ⇒ Boolean
227 228 229 |
# File 'lib/models/service.rb', line 227 def hold? state_str == 'HOLD' end |
#info ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/models/service.rb', line 388 def info rc = super if OpenNebula.is_error?(rc) return rc end @roles = {} if @body['roles'] @body['roles'].each do |elem| elem['state'] ||= Role::STATE['PENDING'] role = Role.new(elem, self) @roles[role.name] = role end end nil end |
#info_roles ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
441 442 443 444 445 446 447 448 449 450 451 452 453 |
# File 'lib/models/service.rb', line 441 def info_roles @roles = {} if @body['roles'] @body['roles'].each do |elem| elem['state'] ||= Role::STATE['PENDING'] role = Role.new(elem, self) @roles[role.name] = role end end nil end |
#log_error(message) ⇒ Object
Add an error message in the service information that will be stored
in OpenNebula
465 466 467 |
# File 'lib/models/service.rb', line 465 def log_error() add_log(Logger::ERROR, ) end |
#log_info(message) ⇒ Object
Add an info message in the service information that will be stored
in OpenNebula
458 459 460 |
# File 'lib/models/service.rb', line 458 def log_info() add_log(Logger::INFO, ) end |
#networks(deploy) ⇒ Array
Returns virtual networks IDs
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/models/service.rb', line 294 def networks(deploy) ret = [] return ret unless @body['networks_values'] @body['networks_values'].each do |vnet| vnet.each do |_, net| next if net.key?('id') && !deploy ret << net['id'].to_i end end ret end |
#on_hold? ⇒ true, false
Returns the on_hold service option
223 224 225 |
# File 'lib/models/service.rb', line 223 def on_hold? @body['on_hold'] end |
#recover ⇒ nil, OpenNebula::Error
Recover a failed service.
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 |
# File 'lib/models/service.rb', line 335 def recover if [Service::STATE['FAILED_DEPLOYING']].include?(state) @roles.each do |_name, role| if role.state == Role::STATE['FAILED_DEPLOYING'] role.set_state(Role::STATE['PENDING']) end end set_state(Service::STATE['DEPLOYING']) elsif state == Service::STATE['FAILED_SCALING'] @roles.each do |_name, role| if role.state == Role::STATE['FAILED_SCALING'] role.set_state(Role::STATE['SCALING']) end end set_state(Service::STATE['SCALING']) elsif state == Service::STATE['FAILED_UNDEPLOYING'] @roles.each do |_name, role| if role.state == Role::STATE['FAILED_UNDEPLOYING'] role.set_state(Role::STATE['RUNNING']) end end set_state(Service::STATE['UNDEPLOYING']) elsif state == Service::STATE['COOLDOWN'] @roles.each do |_name, role| if role.state == Role::STATE['COOLDOWN'] role.set_state(Role::STATE['RUNNING']) end end set_state(Service::STATE['RUNNING']) elsif state == Service::STATE['WARNING'] @roles.each do |_name, role| if role.state == Role::STATE['WARNING'] role.recover_warning end end else OpenNebula::Error.new('Action recover: Wrong state' \ " #{state_str}") end end |
#remove_role(name) ⇒ Object
Removes a role from the service
429 430 431 432 433 434 435 |
# File 'lib/models/service.rb', line 429 def remove_role(name) @roles.delete(name) @body['roles'].delete_if do |role| role['name'] == name end end |
#replace_client(owner_client) ⇒ Object
Replaces this object’s client with a new one
233 234 235 |
# File 'lib/models/service.rb', line 233 def replace_client(owner_client) @client = owner_client end |
#report_ready? ⇒ true, false
Returns the running_status_vm option
209 210 211 |
# File 'lib/models/service.rb', line 209 def report_ready? @body['ready_status_gate'] end |
#running? ⇒ Boolean
Return true if the service is running
203 204 205 |
# File 'lib/models/service.rb', line 203 def running? state_str == 'RUNNING' end |
#set_state(state) ⇒ true, false
Sets a new state rubocop:disable Naming/AccessorMethodName
241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/models/service.rb', line 241 def set_state(state) # rubocop:enable Naming/AccessorMethodName if state < 0 || state > STATE_STR.size return false end @body['state'] = state.to_i msg = "New state: #{STATE_STR[state]}" Log.info LOG_COMP, msg, id log_info(msg) true end |
#shutdown_action ⇒ Object
552 553 554 |
# File 'lib/models/service.rb', line 552 def shutdown_action @body['shutdown_action'] end |
#state ⇒ Integer
Returns the service state
134 135 136 |
# File 'lib/models/service.rb', line 134 def state @body['state'].to_i end |
#state_str ⇒ Object
Returns the string representation of the service state
146 147 148 |
# File 'lib/models/service.rb', line 146 def state_str STATE_STR[state] end |
#strategy ⇒ String
Returns the service strategy
140 141 142 |
# File 'lib/models/service.rb', line 140 def strategy @body['deployment'] end |
#transient_state? ⇒ Boolean
Returns true if the service is in transient state
152 153 154 |
# File 'lib/models/service.rb', line 152 def transient_state? TRANSIENT_STATES.include? STATE_STR[state] end |
#uname ⇒ Object
213 214 215 |
# File 'lib/models/service.rb', line 213 def uname self['UNAME'] end |
#update(template_json = nil, append = false) ⇒ nil, OpenNebula::Error
Replaces the template contents
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
# File 'lib/models/service.rb', line 564 def update(template_json = nil, append = false) if template_json template = JSON.parse(template_json) if append rc = info if OpenNebula.is_error? rc return rc end template = @body.merge(template) end template_json = template.to_json end super(template_json, append) end |
#update_raw(template_raw, append = false) ⇒ nil, OpenNebula::Error
Replaces the raw template contents
592 593 594 |
# File 'lib/models/service.rb', line 592 def update_raw(template_raw, append = false) super(template_raw, append) end |
#update_role(role_name, template_json) ⇒ nil, OpenNebula::Error
Updates a role
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 |
# File 'lib/models/service.rb', line 515 def update_role(role_name, template_json) if ![Service::STATE['RUNNING'], Service::STATE['WARNING']] .include?(state) return OpenNebula::Error.new('Update role: Wrong state' \ " #{state_str}") end template = JSON.parse(template_json) # TODO: Validate template? role = @roles[role_name] if role.nil? return OpenNebula::Error.new("ROLE \"#{role_name}\" " \ 'does not exist') end rc = role.update(template) if OpenNebula.is_error?(rc) return rc end # TODO: The update may not change the cardinality, only # the max and min vms... role.set_state(Role::STATE['SCALING']) role.set_default_cooldown_duration set_state(Service::STATE['SCALING']) update end |