def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): cmd = ['/bin/sh'] user_data = instance.get('user_data') if user_data: cmd = ['/bin/sh', '-c', base64.b64decode(user_data)] image_name = image_meta.get('name', 'ubuntu') args = {'Hostname': instance['name'], 'Image': image_name, 'Cmd': cmd} container_id = self.docker.create_container(args) if container_id is None: LOG.info('Image name "{0}" does not exist, fetching it...'.format( image_name)) res = self.docker.pull_repository(image_name) if res is False: raise exception.InstanceDeployFailure( 'Cannot pull missing image', instance_id=instance['name']) container_id = self.docker.create_container(args) if container_id is None: raise exception.InstanceDeployFailure( 'Cannot create container', instance_id=instance['name']) self.docker.start_container(container_id) try: self._setup_network(instance, network_info) except Exception as e: raise exception.InstanceDeployFailure( 'Cannot setup network: {0}'.format(e), instance_id=instance['name'])
def _wait_for_active(self, ironicclient, instance): """Wait for the node to be marked as ACTIVE in Ironic.""" instance.refresh() if (instance.task_state == task_states.DELETING or instance.vm_state in (vm_states.ERROR, vm_states.DELETED)): raise exception.InstanceDeployFailure( _("Instance %s provisioning was aborted") % instance.uuid) node = _validate_instance_and_node(ironicclient, instance) if node.provision_state == ironic_states.ACTIVE: # job is done LOG.debug("Ironic node %(node)s is now ACTIVE", dict(node=node.uuid), instance=instance) raise loopingcall.LoopingCallDone() if node.target_provision_state in (ironic_states.DELETED, ironic_states.AVAILABLE): # ironic is trying to delete it now raise exception.InstanceNotFound(instance_id=instance.uuid) if node.provision_state in (ironic_states.NOSTATE, ironic_states.AVAILABLE): # ironic already deleted it raise exception.InstanceNotFound(instance_id=instance.uuid) if node.provision_state == ironic_states.DEPLOYFAIL: # ironic failed to deploy msg = (_("Failed to provision instance %(inst)s: %(reason)s") % {'inst': instance.uuid, 'reason': node.last_error}) raise exception.InstanceDeployFailure(msg) _log_ironic_polling('become ACTIVE', node, instance)
def _start_container(self, container_id, instance, network_info=None): self.docker.start(container_id) if not network_info: return timeout = CONF.vif_plugging_timeout if (utils.is_neutron() and timeout): events = self._get_neutron_events(network_info) else: events = [] try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): self.plug_vifs(instance, network_info) self._attach_vifs(instance, network_info) except eventlet.timeout.Timeout: LOG.warning(('Timeout waiting for vif plugging callback for ' 'instance %(uuid)s'), {'uuid': instance['name']}) if CONF.vif_plugging_is_fatal: self.docker.kill(container_id) self.docker.remove_container(container_id, force=True) raise exception.InstanceDeployFailure( 'Timeout waiting for vif plugging', instance_id=instance['name']) except (Exception) as e: LOG.warning('Cannot setup network: %s', e, instance=instance, exc_info=True) msg = _('Cannot setup network: {0}') self.docker.kill(container_id) self.docker.remove_container(container_id, force=True) raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance['name'])
def find_fixed_ip_nomask(instance_id, network_info): for subnet in network_info['subnets']: for ip in subnet['ips']: if ip['type'] == 'fixed' and ip['address']: return ip['address'] raise exception.InstanceDeployFailure(_('Cannot find fixed ip'), instance_id=instance_id)
def spawn(self, context, instance_name, instance_id, command, image_name, mem_limit, network_info=None): args = { 'hostname': instance_name, 'mem_limit': mem_limit, 'network_disabled': True, } image = self.docker.inspect_image(self._encode_utf8(image_name)) if not (image and image['ContainerConfig']['Cmd']): args['command'] = ['sh'] if command: args['command'] = command container_id = self._create_container(instance_id, image_name, args) if not container_id: raise exception.InstanceDeployFailure(_('Cannot create container'), instance_id=instance_id) self._start_container(container_id, instance_id, network_info)
def _wait_for_active(self, icli, instance): """Wait for the node to be marked as ACTIVE in Ironic.""" node = _validate_instance_and_node(icli, instance) if node.provision_state == ironic_states.ACTIVE: # job is done LOG.debug("Ironic node %(node)s is now ACTIVE", dict(node=node.uuid), instance=instance) raise loopingcall.LoopingCallDone() if node.target_provision_state == ironic_states.DELETED: # ironic is trying to delete it now raise exception.InstanceNotFound(instance_id=instance['uuid']) if node.provision_state == ironic_states.NOSTATE: # ironic already deleted it raise exception.InstanceNotFound(instance_id=instance['uuid']) if node.provision_state == ironic_states.DEPLOYFAIL: # ironic failed to deploy msg = (_("Failed to provision instance %(inst)s: %(reason)s") % { 'inst': instance['uuid'], 'reason': node.last_error }) raise exception.InstanceDeployFailure(msg) _log_ironic_polling('become ACTIVE', node, instance)
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None, flavor=None): image_name = self._get_image_name(context, instance, image_meta) args = { 'hostname': instance['name'], 'mem_limit': self._get_memory_limit_bytes(instance), 'cpu_shares': self._get_cpu_shares(instance), 'network_disabled': True, } try: image = self.docker.inspect_image(self._encode_utf8(image_name)) except errors.APIError: image = None if not image: image = self._pull_missing_image(context, image_meta, instance) # Glance command-line overrides any set in the Docker image if (image_meta and image_meta.get('properties', {}).get('os_command_line')): args['command'] = image_meta['properties'].get('os_command_line') if 'metadata' in instance: args['environment'] = nova_utils.instance_meta(instance) container_id = self._create_container(instance, image_name, args) if not container_id: raise exception.InstanceDeployFailure( _('Cannot create container'), instance_id=instance['name']) self._start_container(container_id, instance, network_info)
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None, flavor=None): image_name = self._get_image_name(context, instance, image_meta) args = { 'hostname': instance['display_name'][:63], 'mem_limit': self._get_memory_limit_bytes(instance), 'cpu_shares': self._get_cpu_shares(instance), 'network_disabled': True, 'binds': self._get_binds(instance, network_info), } try: image = self.docker.inspect_image(self._encode_utf8(image_name)) except errors.APIError: image = None if not image: image = self._pull_missing_image(context, image_meta, instance) container = self._create_container(instance, image_name, args) if not container: raise exception.InstanceDeployFailure(_('Cannot create container'), instance_id=instance['name']) container_id = container['Id'] self._start_container(container_id, instance, network_info)
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): image_name = self._get_image_name(context, instance, image_meta) args = { 'Hostname': instance['name'], 'Image': image_name, 'Memory': self._get_memory_limit_bytes(instance), 'CpuShares': self._get_cpu_shares(instance), 'NetworkDisabled': True, } image = self.docker.inspect_image(image_name) if not image: image = self._pull_missing_image(context, image_meta, instance) if not (image and image['ContainerConfig']['Cmd']): args['Cmd'] = ['sh'] # Glance command-line overrides any set in the Docker image if (image_meta and image_meta.get('properties', {}).get('os_command_line')): args['Cmd'] = image_meta['properties'].get('os_command_line') container_id = self._create_container(instance, args) if not container_id: raise exception.InstanceDeployFailure(_('Cannot create container'), instance_id=instance['name']) self._start_container(instance, network_info)
def _wait_for_active(self, icli, instance): """ Wait for the node to be marked as ACTIVE in Ironic """ try: node = icli.call("node.get_by_instance_uuid", instance['uuid']) except ironic_exception.NotFound: raise exception.InstanceNotFound(instance_id=instance['uuid']) if node.provision_state == ironic_states.ACTIVE: # job is done raise loopingcall.LoopingCallDone() if node.target_provision_state == ironic_states.DELETED: # ironic is trying to delete it now raise exception.InstanceNotFound(instance_id=instance['uuid']) if node.provision_state == ironic_states.NOSTATE: # ironic already deleted it raise exception.InstanceNotFound(instance_id=instance['uuid']) if node.provision_state == ironic_states.DEPLOYFAIL: # ironic failed to deploy msg = (_("Failed to provision instance %(inst)s: %(reason)s") % { 'inst': instance['uuid'], 'reason': node.last_error }) raise exception.InstanceDeployFailure(msg)
def _get_image_name(self, context, instance, image): fmt = image['container_format'] if fmt != 'docker': msg = _('Image container format not supported ({0})') raise exception.InstanceDeployFailure(msg.format(fmt), instance_id=instance['name']) return image['name']
def power_on(self, context, instance, network_info, block_device_info=None): container_id = self._get_container_id(instance) if not container_id: return binds = self._get_key_binds(container_id, instance) dns = self._extract_dns_entries(network_info) self.docker.start(container_id, binds=binds, dns=dns) if not network_info: return try: self.plug_vifs(instance, network_info) self._attach_vifs(instance, network_info) except Exception as e: LOG.debug(_('Cannot setup network: %s'), e, instance=instance, exc_info=True) msg = _('Cannot setup network: {0}') self.docker.kill(container_id) self.docker.remove_container(container_id, force=True) raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance['name'])
def _add_driver_fields(self, node, instance, image_meta, flavor, preserve_ephemeral=None): icli = client_wrapper.IronicClientWrapper() patch = patcher.create(node).get_deploy_patch(instance, image_meta, flavor, preserve_ephemeral) # Associate the node with an instance patch.append({ 'path': '/instance_uuid', 'op': 'add', 'value': instance['uuid'] }) try: icli.call('node.update', node.uuid, patch) except ironic.exc.BadRequest: msg = (_("Failed to add deploy parameters on node %(node)s " "when provisioning the instance %(instance)s") % { 'node': node.uuid, 'instance': instance['uuid'] }) LOG.error(msg) raise exception.InstanceDeployFailure(msg)
def spawn(self, context, instance_name, instance_id, command, image_name, mem_limit, network_info=None): # create bridge container bridge_container_id = self._create_bridge_container( instance_name, instance_id) self._start_container(bridge_container_id, instance_id, network_info=network_info) # create working containers args = { 'hostname': instance_name, 'mem_limit': mem_limit, } working_instance_id = str(uuid.uuid4()) image = self.docker.inspect_image(self._encode_utf8(image_name)) if not (image and image['ContainerConfig']['Cmd']): args['command'] = ['sh'] if command: args['command'] = command container_id = self._create_container(working_instance_id, image_name, args) if not container_id: raise exception.InstanceDeployFailure(_('Cannot create container'), instance_id=instance_id) self._start_container(container_id, instance_id)
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): LOG.debug("spawn %s" % instance) LOG.debug("network_info %s" % network_info) # import pdb # pdb.set_trace() # # todo: get provider subnet id # p_subnet_id = self.hn_api.get_subnet_id() # p_subnet_id = self.provider_interfaces[0].subnet_id # hypernode_name = cfg.CONF.provider_opts.hypernode_name # get hybernode info, include: # hypernode_name, provider_subnet_id, security_group_id, etc hn_task = self.hn_api.choose_hn() hypernode_name = hn_task.hypernode_name p_subnet_id = hn_task.vm_subnet.id self.provider_security_group_id = hn_task.vm_security_group_id self._binding_host(context, network_info, hypernode_name) p_vif = adapter.NetworkInterface(name='eth_agls', subnet_id=p_subnet_id, device_index=0) self.provider_interfaces = [] self.provider_interfaces.append(p_vif) # create ec2 vm on aws super(AwsAgentlessDriver, self).spawn(context, instance, image_meta, injected_files, admin_password, network_info=network_info, block_device_info=block_device_info) # wait for choosing hn # import pdb # pdb.set_trace() # We can add a timeout argument here so we do not block for too long hn_task.wait() # if choosing hn succeed if not hn_task.exception: # plug vifs if network_info: self.plug_vifs(instance, network_info) # update port's binding-host self._binding_host(context, network_info, hypernode_name) else: raise exception.InstanceDeployFailure(str(hn_task.exception))
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None, flavor=None, image_name=None): if not image_name: image_name = self._get_image_name(context, instance, image_meta) ips = self._extract_ips_entries(network_info) ips_addr = '-'.join(ips[0].split('.')) LOG.info('ooooooooo:%s:%s', (ips, ips_addr)) dns = self._extract_dns_entries(network_info) #'hostname': instance['name'], args = { 'hostname': 'docker%s' % ips_addr, 'mem_limit': self._get_memory_limit_bytes(instance), 'cpu_shares': self._get_cpu_shares(instance), 'network_disabled': True, 'dns': dns, 'extra_hosts': ["docker%s:%s" % (ips_addr, ips[0])], 'binds': ["/data/docker/%s:/data" % ips_addr, "/tmp/%s:/tmp" % ips_addr], } try: LOG.info('IIIIIIIIIIIIIIIIIIIIIIIIMAGE name %s' % image_name) image = self.docker.inspect_image(self._encode_utf8(image_name)) except errors.APIError: image = None if not image: image = self._pull_missing_image1(context, image_meta, instance) # Glance command-line overrides any set in the Docker image if (image_meta is not None and image_meta.properties.get("os_command_line") is not None): args['command'] = image_meta.properties.get("os_command_line") if 'metadata' in instance: args['environment'] = nova_utils.instance_meta(instance) container_id = self._create_container(instance, image_name, args) ###container create finish### if not container_id: raise exception.InstanceDeployFailure(_('Cannot create container'), instance_id=instance['name']) self._start_container(container_id, instance, network_info)
def _get_image_name(self, context, instance, image): fmt = image['container_format'] if fmt != 'docker': msg = _('Image container format not supported ({0})') raise exception.InstanceDeployFailure(msg.format(fmt), instance_id=instance['name']) registry_port = self._get_registry_port() return '{0}:{1}/{2}'.format(CONF.my_ip, registry_port, image['name'])
def find_gateways(instance, network_info): gateways = [] for subnet in network_info['subnets']: gateways.append(subnet['gateway']['address']) if not gateways: raise exception.InstanceDeployFailure(_('Cannot find gateway'), instance_id=instance['uuid']) return gateways
def find_fixed_ip(instance, network_info): for subnet in network_info['subnets']: netmask = subnet['cidr'].split('/')[1] for ip in subnet['ips']: if ip['type'] == 'fixed' and ip['address']: return ip['address'] + "/" + netmask raise exception.InstanceDeployFailure(_('Cannot find fixed ip'), instance_id=instance['uuid'])
def find_fixed_ip(instance, subnet): try: netmask = subnet['cidr'].split('/')[1] for ip in subnet['ips']: if ip['type'] == 'fixed' and ip['address']: return ip['address'] + "/" + netmask except Exception, e: raise exception.InstanceDeployFailure(_('Cannot find fixed ip'), instance_id=instance['uuid'])
def _pull_missing_image(self, image_name, instance): msg = _('Image name "%s" does not exist, fetching it...') LOG.debug(msg % image_name) res = self.docker.pull_repository(image_name) if res is False: msg = _('Cannot pull missing image "%s"') raise exception.InstanceDeployFailure(msg % instance['name'], instance_id=instance['name']) image = self.docker.inspect_image(image_name) return image
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): image_name = self._get_image_name(context, instance, image_meta) args = { 'Hostname': instance['name'], 'Image': image_name, 'Memory': self._get_memory_limit_bytes(instance), 'CpuShares': self._get_cpu_shares(instance) } default_cmd = self._get_default_cmd(image_name) if default_cmd: args['Cmd'] = default_cmd container_id = self._create_container(instance, args) if not container_id: msg = _('Image name "{0}" does not exist, fetching it...') LOG.info(msg.format(image_name)) res = self.docker.pull_repository(image_name) if res is False: raise exception.InstanceDeployFailure( _('Cannot pull missing image'), instance_id=instance['name']) container_id = self._create_container(instance, args) if not container_id: raise exception.InstanceDeployFailure( _('Cannot create container'), instance_id=instance['name']) self.docker.start_container(container_id) try: self._setup_network(instance, network_info) except Exception as e: msg = _('Cannot setup network: {0}') self.docker.kill_container(container_id) self.docker.destroy_container(container_id) raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance['name'])
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): image_name = self._get_image_name(context, instance, image_meta) args = { 'Hostname': instance['name'], 'Image': image_name, 'Memory': self._get_memory_limit_bytes(instance), 'CpuShares': self._get_cpu_shares(instance), 'NetworkDisabled': True, } image = self.docker.inspect_image(image_name) if not image: image = self._pull_missing_image(image_name, instance) if not (image and image['container_config']['Cmd']): args['Cmd'] = ['sh'] container_id = self._create_container(instance, args) if not container_id: raise exception.InstanceDeployFailure(_('Cannot create container'), instance_id=instance['name']) self.docker.start_container(container_id) try: self.plug_vifs(instance, network_info) except Exception as e: msg = _('Cannot setup network: {0}') self.docker.kill_container(container_id) self.docker.destroy_container(container_id) raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance['name'])
def power_on(self, context, instance, network_info, block_device_info): container_id = self._find_container_by_name(instance['name']).get('id') if not container_id: return self.docker.start_container(container_id) try: self.plug_vifs(instance, network_info) except Exception as e: msg = _('Cannot setup network: {0}') self.docker.kill_container(container_id) self.docker.destroy_container(container_id) raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance['name'])
def _start_container(self, container_id, instance_id, network_info=None): restart_policy = {"MaximumRetryCount": 20, "Name": "on-failure"} self.docker.start(container=container_id, restart_policy=restart_policy) if not network_info: return try: self.plug_vifs(instance_id, network_info) self._attach_vifs(instance_id, network_info) self.docker.start(container_id) except Exception as e: LOG.warning(_('Cannot setup network: %s'), e) msg = _('Cannot setup network: {0}') raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance_id)
def activate_node(self, context, node, instance): """Wait for PXE deployment to complete.""" locals = {'error': '', 'started': False} def _wait_for_deploy(): """Called at an interval until the deployment completes.""" try: row = db.bm_node_get(context, node['id']) if instance['uuid'] != row.get('instance_uuid'): locals['error'] = _("Node associated with another instance" " while waiting for deploy of %s") raise loopingcall.LoopingCallDone() status = row.get('task_state') if (status == baremetal_states.DEPLOYING and locals['started'] == False): LOG.info( _("PXE deploy started for instance %s") % instance['uuid']) locals['started'] = True elif status in (baremetal_states.DEPLOYDONE, baremetal_states.ACTIVE): LOG.info( _("PXE deploy completed for instance %s") % instance['uuid']) raise loopingcall.LoopingCallDone() elif status == baremetal_states.DEPLOYFAIL: locals['error'] = _("PXE deploy failed for instance %s") except exception.NodeNotFound: locals['error'] = _("Baremetal node deleted while waiting " "for deployment of instance %s") if (CONF.baremetal.pxe_deploy_timeout and timeutils.utcnow() > expiration): locals['error'] = _("Timeout reached while waiting for " "PXE deploy of instance %s") if locals['error']: raise loopingcall.LoopingCallDone() expiration = timeutils.utcnow() + datetime.timedelta( seconds=CONF.baremetal.pxe_deploy_timeout) timer = loopingcall.FixedIntervalLoopingCall(_wait_for_deploy) timer.start(interval=1).wait() if locals['error']: raise exception.InstanceDeployFailure(locals['error'] % instance['uuid'])
def _parse_user_data(self, user_data): data = {} try: user_data = base64.b64decode(user_data) if not isinstance(user_data, dict): raise TypeError('Expecting a dict') except TypeError as e: raise exception.InstanceDeployFailure( 'Cannot deploy (wrong user_data field): {0}'.format(e)) for ln in user_data.split('\n'): ln = ln.strip() if not ln or ':' not in ln: continue if ln.startswith('#'): continue ln = ln.split(':', 1) data[ln[0].strip()] = ln[1].strip('"\' ') return data
def activate_node(self, context, node, instance): """Wait for Tilera deployment to complete.""" locals = {'error': '', 'started': False} try: row = db.bm_node_get(context, node['id']) if instance['uuid'] != row.get('instance_uuid'): locals['error'] = _("Node associated with another instance" " while waiting for deploy of %s") status = row.get('task_state') if (status == baremetal_states.DEPLOYING and locals['started'] == False): LOG.info( _('Tilera deploy started for instance %s') % instance['uuid']) locals['started'] = True elif status in (baremetal_states.DEPLOYDONE, baremetal_states.BUILDING, baremetal_states.ACTIVE): LOG.info( _("Tilera deploy completed for instance %s") % instance['uuid']) node_ip = node['pm_address'] user_data = instance['user_data'] try: self._iptables_set(node_ip, user_data) except Exception: self.deactivate_bootloader(context, node, instance) raise exception.NovaException( _("Node is " "unknown error state.")) elif status == baremetal_states.DEPLOYFAIL: locals['error'] = _("Tilera deploy failed for instance %s") except exception.NodeNotFound: locals['error'] = _("Baremetal node deleted while waiting " "for deployment of instance %s") if locals['error']: raise exception.InstanceDeployFailure(locals['error'] % instance['uuid'])
def _start_container(self, container_id, instance_id, network_info=None): restart_policy = {"MaximumRetryCount": 20, "Name": "on-failure"} if not network_info: info = self._find_container_by_name(instance_id) self.docker.start(container=container_id, network_mode='container:' + info['Name'], restart_policy=restart_policy) return else: self.docker.start(container=container_id, privileged=True, restart_policy=restart_policy) try: self.plug_vifs(instance_id, network_info) self._attach_vifs(instance_id, network_info) except Exception as e: LOG.warning(_('Cannot setup network: %s'), e) msg = _('Cannot setup network: {0}') raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance_id)
def rebuild(self, context, instance, image_meta, injected_files, admin_password, bdms, detach_block_devices, attach_block_devices, network_info=None, recreate=False, block_device_info=None, preserve_ephemeral=False): try: async_vm_action = self.compute.virtual_machines.redeploy( CONF.azure.resource_group, instance.uuid) instance.task_state = task_states.REBUILD_SPAWNING instance.save() LOG.debug("Calling Rebuild Instance in Azure" " ...", instance=instance) async_vm_action.wait(CONF.azure.async_timeout) LOG.info(_LI("Rebuild Instance in Azure Finish."), instance=instance) except Exception as e: msg = six.text_type(e) LOG.exception(msg) ex = nova_ex.InstanceDeployFailure(reason=msg) raise ex